聊一聊区块链-波场技术, 只聊技术

这篇具有很好参考价值的文章主要介绍了聊一聊区块链-波场技术, 只聊技术。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

聊一聊区块链-波场技术, 只聊技术

前言

最近因项目使用 tron 协议接入区块链, 故对其做了一番研究, 先把相关资料整理一遍, 供大家学习使用;

网上的这部分资料很少, 所以学习起来也是遇到了很多困难, 尤其是里面很多新的概念, 理解起来有一定的难度。比如说去中心化、地址、加密算法、算法因子、私钥含义、助记词、trc 协议、智能合约、usdt 等等;

背景

很多人接触区块链, 大多是通过接触 usdt 这种中充当稳定资产(也称泰达币)角色开始的, usdt 是什么? 下面我们探讨一下这个问题。

USDT 是一种将加密货币与法定货币美元挂钩的虚拟货币 , 一种基本衡量单位的代币; Tether 公司推出的基于稳定价值货币美元(USD)的代币 Tether USD(下称 USDT), 1USDT=1 美元, 用户可以随时使用 USDT 与 USD 进行 1:1 兑换。

公司对外宣称严格遵守 1: 1 的准备金保证, 即每发行 1 个 USDT 代币, 其银行账户都会有 1 美元的资金保障。用户可以在 Tether 平台进行资金查询, 以保障透明度这样然后 usdt 稳定资产发行者通过存入三方银行机构法定资产, 来保证我的 usdt 是有保证的, 不会超发或者失去赔付能力;

我们怎么知道 Tether 公司所说的真实性呢?

这一点我们通过 Tether 官网 (https://tether.to/en/supported-protocols/) 进行查看, 进入透明度 (https://tether.to/en/transparency/) 展示界面, 可以看到其发行了多少枚代币, 以及质押情况。

可以看到, 不光有 USDT, 还有 ESDT、CSDT ; 其实 U 是代表美国, E 代表欧洲, C 代表中国的意思。

波场链

TRON 是一个开源同时支持智能合约功能的公共区块链平台, 也叫波场链。其创始人是中国人孙宇晨, 他拍过巴菲特的午餐, 牛。好了, 废话不多说, 介绍一些东西吧。

区块链是什么

既然我们很多时候提到了链, 那链到底是什么呢?

其实链可以理解为一个平台, 这个平台能够做一些事情。比如运行智能合约, 发行代币等等。当然构建一个去中心化的链就必须要实现一些机制, 比如构建信任机制, 这是去中心化核心中的核心。说到这里要引入一个概念: 共识。即如何在分布式的不信任环境中搭建一个信任的网络?

共识

在区块链系统中没有像银行一样的中心化机构, 所以在进行传输信息、价值转移时, 共识机制解决并保证每一笔交易在所有记帐节点上的一致性和 正确性问题。区块链的这种新的共识机制使其在不依靠中心化组织的情况下, 依然大规模高效协作完成运转。

工作量证明 Pow

工作量证明简单理解就是一份证明, 用来确认节点做过一定量的工作。监测工作的整个过程通常是极为低效的, 而通过对工作的结果进行认证来证明完成了相应的工作量, 则是-种非常高效的方式。比特币在区块的生成过程中使用了 PoW 机制, 要得到合理的随机数求解数学难题需要经过大量尝试计算, 通过查看记录和验证区块链信息的证明, 就能知道是否完成了指定难度系数的工作量。

权益证明 Pos

即把资产存在银行里, 银行会通过你持有数字资产的数量和时间给你分配相应的收益。采用 PoS 机制的加密货币资产, 系统会根据节点的持币数量和时间的乘积(币天数)给节点分配相应的权益。

还有一些其他的共识机制, 这里介绍了两种最为广泛和常见的共识机制。

节点

TRON 是一个由很多计算机组成的分布式网络, 计算机上需要运行可以验证区块和交易数据的软件, 也叫节点。您需要在系统上安装运行一个叫做客户端的软件, 才能运行一个节点。

"节点 "指的是一个正在运行的客户端软件。客户端是 TRON 的一个实现, 它可以验证每个区块的所有交易, 保持网络的安全和数据的准确性。目前 TRON 客户端是由 Java 语言实现, 它遵循 TRON 协议, 实现了 TRON 网络和区块链的功能。

每个人可以下载相关源代码, 并运行节点的客户端, 可以自行验证交易; 也可以理解"节点 "指的是一个正在运行的客户端软件。客户端是 TRON 的一个实现, 它可以验证每个区块的所有交易, 保持网络的安全和数据的准确性。

区块

区块是一个包含了一系列交易的集合, 另外一个区块还包含了前一个区块的哈希值, 这种实现方式将各个区块连接到一起形成链。

为了确保 TRON 网络上的所有节点保持一致的状态并就交易的历史达成一致, 我们将交易打包进区块, 实现了数百个交易同时被提交、确认以及同步到全网。每个新创建的区块都包含其父区块的 hash 值。在任何给定的时间, 网络上的几乎所有节点都对区块的数量和历史状态达成一致。

代币 Trx

TRX 是 TRON 网络上最主要的加密货币, 就像是以太坊的链上的代币就是 eth; TRX 是 TRON 区块链上帐户的基本单位, 在 tron 链上进行的交易活动花费以 trx 作为标准衡量。

TRX 可以被铸造、销毁、转移等行为; 有了这些功能, 我们才能理解后面为啥会有 TRC20-USDT 的概念了?

  • TRC20 协议标准

我们知道 TRON 链支持运行智能合约, 而我们熟知的 TRC20, 其实就是一种合约, 这个合约里面实现了一些功能, 比如代币查询、转移、授权等等功能。
TRC-20 是为发行通证资产而制定的一套合约标准, 即遵守这一标准编写的合约都被认为是一个 TRC-20 合约。当各类钱包、交易所在对接 TRC-20 合约的资产时, 从这套合约标准中就可以知道这个合约定义了哪些函数、事件, 从而方便的进行对接。

要明白 trc20 是一种协议, 这个协议是波场 tron 链下面的一种, 还有 trx, trc10, trc721 等等, 而波场链跟 usdt 发行者公司合作, 写了一份智能合约, 该协议实现了几种功能, 如交易、查询、授权、事件监听等等, 我们在地址中转账看到的 trc20-usdt 就是执行了这个交易方法 transfer, 所以能够把一个地址中的 usdt 转移到另一个地址;

//trc20 协议中支持的方法
contract TRC20 {
    function totalSupply() constant returns (uint theTotalSupply);
    function balanceOf(address _owner) constant returns (uint balance);
    function transfer(address _to, uint _value) returns (bool success);
    function transferFrom(address _from, address _to, uint _value) returns (bool success);
    function approve(address _spender, uint _value) returns (bool success);
    function allowance(address _owner, address _spender) constant returns (uint remaining);
    event Transfer(address indexed _from, address indexed _to, uint _value);
    event Approval(address indexed _owner, address indexed _spender, uint _value);
}

这下会明白了? 为什么出现了 TRC20-USDT 这个词, 其原因就是如此。同理, 在 eth 链上实现一个支持 USDT 交易的智能合约, 那这个链就能通过 ETH 进行转账交易, 比如说 erc20-usdt。

Trc20-usdt

转账

要实现交易, 首先要得有地址, 自己地址, 对方地址, usdt, trx 燃料费; 然后这几个要素经过什么步骤才能达到目的?

  • 创建交易 、离线签名、广播

先把代码贴出来:

/**
     * 发起 trc20 交易 (目标地址, 数量, 合约地址, 私钥)
     * 地址 默认为 usdt 合约地址
     * @throws Throwable
     */
    public String sendTrc20(String toAddress, BigDecimal amount, String privateKey) throws Throwable {
        String ownerAddress = TronUtils.getAddressByPrivateKey(privateKey);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("contract_address", TronUtils.toHexAddress(USDT_CPNTRACT));
        jsonObject.put("function_selector", "transfer(address,uint256)");
        List<Type> inputParameters = new ArrayList<>();
        inputParameters.add(new Address(TronUtils.toHexAddress(toAddress).substring(2)));
        inputParameters.add(new Uint256(amount.multiply(decimal).toBigInteger()));
        String parameter = FunctionEncoder.encodeConstructor(inputParameters);
        jsonObject.put("parameter", parameter);
        jsonObject.put("owner_address", TronUtils.toHexAddress(ownerAddress));
        jsonObject.put("call_value", 0);
        jsonObject.put("fee_limit", 6000000L);
        String trans1 = HttpClientUtils.postJson(tronUrl + "/wallet/triggersmartcontract", jsonObject.toString());
        JSONObject result = JSONObject.parseObject(trans1);
        System.out.println("trc20 result:" + result.toJSONString());
        if (result.containsKey("Error")) {
            throw new RuntimeException("result.containsKey(\"Error\")");
        }
        JSONObject tx = result.getJSONObject("transaction");
        //填写备注
        tx.getJSONObject("raw_data").put("data", Hex.toHexString("备注信息".getBytes()));
        String txid = TronUtils.signAndBroadcast(tronUrl, privateKey, tx);
        if (txid != null) {
            System.out.println("txid:" + txid);
            return txid;
        }
        return null;
    }

创建交易

String ownerAddress = TronUtils.getAddressByPrivateKey(privateKey);
JSONObject jsonObject = new JSONObject();
jsonObject.put("contract_address", TronUtils.toHexAddress(USDT_CPNTRACT));
jsonObject.put("function_selector", "transfer(address,uint256)");
List<Type> inputParameters = new ArrayList<>();
inputParameters.add(new Address(TronUtils.toHexAddress(toAddress).substring(2)));
inputParameters.add(new Uint256(amount.multiply(decimal).toBigInteger()));
String parameter = FunctionEncoder.encodeConstructor(inputParameters);
jsonObject.put("parameter", parameter);
jsonObject.put("owner_address", TronUtils.toHexAddress(ownerAddress));
jsonObject.put("call_value", 0);
jsonObject.put("fee_limit", 6000000L);
String trans1 = HttpClientUtils.postJson(tronUrl + "/wallet/triggersmartcontract", jsonObject.toString());
JSONObject result = JSONObject.parseObject(trans1);
System.out.println("trc20 result:" + result.toJSONString());
        if (result.containsKey("Error")) {
            throw new RuntimeException("result.containsKey(\"Error\")");
        }
        JSONObject tx = result.getJSONObject("transaction");
        //填写备注
        tx.getJSONObject("raw_data").put("data", Hex.toHexString("备注信息".getBytes()));

先通过私钥获取自己的地址, 然后指定合约地址, 即 usdt 在波场的合约地址, 指定合约中的方法; 然后指定对方地址、附上燃料费 trx , 通过调用 /wallet/triggersmartcontract 创建交易; 至此第一步就算完成了;

这里需要说明, trx 燃料费的概念, 也就是支付给区块链节点的矿工费用; 如果没有 trx 交易是不成功的; 很多人疑惑, 为啥用交易所不需要 trx, 那是因为交易所帮你给付了, 用 web3 wallet 转, 必须支付 trx;

  • 签名和广播
public static String signAndBroadcast(String tronUrl,String privateKey,JSONObject transaction)throws Throwable{
        if(tronUrl.endsWith("/")){
            tronUrl= tronUrl.substring(0,tronUrl.length() - 1);
        }
        Protocol.Transaction tx = packTransaction(transaction.toJSONString());
        byte[] bytes = signTransactionByte(tx.toByteArray(), ByteArray.fromHexString(privateKey));
        String signTransation = Hex.toHexString(bytes);
        JSONObject jsonObjectGB = new JSONObject();
        jsonObjectGB.put("transaction", signTransation);
        String url = tronUrl + "/wallet/broadcasthex";
        String transationCompelet1 = HttpClientUtils.postJson(url, jsonObjectGB.toString());
        JSONObject transationCompelet = JSONObject.parseObject(transationCompelet1);
        System.out.println("signAndBroadcast transationCompelet:" + transationCompelet.toJSONString());
        if (transationCompelet.getBoolean("result")) {
            return transationCompelet.getString("txid");
        } else {
            logger.error(String.format("签名交易失败: %s",transationCompelet1));
            return null;
        }
    }
    /**
     * 签名交易
     * @param transaction
     * @param privateKey
     * @return
     * @throws InvalidProtocolBufferException
     * @throws NoSuchAlgorithmException
     */
    public static byte[] signTransactionByte(byte[] transaction, byte[] privateKey) throws InvalidProtocolBufferException, NoSuchAlgorithmException {
        ECKey ecKey = ECKey.fromPrivate(privateKey);
        Protocol.Transaction transaction1 = Protocol.Transaction.parseFrom(transaction);
        byte[] rawdata = transaction1.getRawData().toByteArray();
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        digest.update(rawdata,0,rawdata.length);
        byte[] hash= digest.digest();
        byte[] sign = ecKey.sign(hash).toByteArray();
        return transaction1.toBuilder().addSignature(ByteString.copyFrom(sign)).build().toByteArray();
    }
  • 签名验证的原理

在已知交易发起者(contract owner)地址的情况下, 通过签名消息逆推公钥(recover), 并将公钥转换为地址, 与发起者地址进行比较。如果地址一致, 即为验证成功。

  • 验证签名的方法

验证方法需要三个参数:

  • 交易 id(即交易哈希, 通过 Transaction.rawData 计算 SHA256 得到)
  • 签名消息(即 Transaction.signature)
  • 发起者地址(即 Transaction.rawData.contract.parameter.ownerAddress, 其中 parameter 的类型是 com.google.protobuf.Any, 需要根据具体交易类型来进行 unpack 操作)
byte[] bytes = signTransactionByte(tx.toByteArray(), ByteArray.fromHexString(privateKey));
String signTransation = Hex.toHexString(bytes);
  • 广播

广播可理解为发送交易。任何与波场网络的交互行为都被称作为一笔交易。一笔交易可以是 TRX 转账、质押/解锁 TRX、触发智能合约等。

只有消耗资源的交易才会被记录在链上。前面提到了 trx 燃料费, 就是这里的消耗的资源; 当区块链的其他节点确认了你的交易, 并把此笔交易广播给其他人后, 这笔交易就算交易成功, 即同步到其他节点的数据库了;

wrapper.broadcastTransaction(signedTransaction); //return transaction hash if successfully broadcasted, otherwise the error code

String url = tronUrl + "/wallet/broadcasthex";
String transationCompelet1 = HttpClientUtils.postJson(url, jsonObjectGB.toString());
JSONObject transationCompelet = JSONObject.parseObject(transationCompelet1);

以上就是 trc20-usdt 转账的背后逻辑。下面讲讲 wallet 地址以及 wallet 地址的创建和生成;

账户与地址

TRON 采用账户模型, 账户的唯一标识为地址(address), 对账户操作需要私钥签名。帐户由一对加密密钥组成: 公钥和私钥。公钥映射为地址, 私钥用来对交易进行签名。这对密钥不但可以防止交易被篡改和伪造, 而且还可以证明交易确实是由发送方所发送。私钥由 64 个十六进制字符组成。公钥的生成基于私钥, 并使用椭圆曲线数字签名算法(https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm)来生成对应的公钥。基于公钥可以计算出地址。

账户地址格式

TRON 网络账户地址有两种格式, 一种是 Hex 格式, 另一种是 Base58 格式。

Hex 格式: 用公钥 P 作为输入, 计算 SHA3 得到结果 H, 取 H 的最后 20 字节, 在前面填充一个字节 0x41 得到 Hex 格式地址。例如:

418840E6C55B9ADA326D211D818C34A994AECED808

Base58 格式: 对 hex 格式的地址进行 basecheck 计算得到 Base58 格式地址, 所有账户地址的第一个字符均为 T。例如:

TNPeeaaFB7K9cmo4uQpcU32zGK8G1NYqeL

我们经常看的和使用的就是 Base58 格式的地址。

  • 钱包是什么

wallet 钱包可以理解为 管理账户中的地址和私钥的工具, 这些工具可以是 app, 或者网站; 我们称这些工具为钱包, 比如我们常用的钱包 imToken、tronLink 等等。在使用 web3 wallet 时, 经常会让我们主动创建或导入住记词、私钥的方式创建 wallet, 这后面的原理又是什么呢?

我们可以理解 wallet 钱包地址是这套算法中公钥, 这个地址是公开的, 别人可以向你进行交易等等; 而经常说的助记词就是把私钥经过可逆算法转换成了 12 个常见的英文字符串, 二者是等价的(这个过程和产生 wallet 地址、私钥算法不一样), 明白加密算法的人都知道, 加密算法一般不具备可逆向性的, 私钥能推导出公钥的, 反之不行。所以务必保护好你的私钥及代表私钥的助记词。

好了, 明白这些东西后, 那我们看代码:

    /**
     * 离线创建地址
     *
     * @return
     */
    public static Map<String, String> createAddress() {
        ECKey eCkey = new ECKey(random);
    String privateKey = ByteArray.toHexString(eCkey.getPrivKeyBytes());
        byte[] addressBytes = eCkey.getAddress();
        String hexAddress = ByteArray.toHexString(addressBytes);
        Map<String, String> addressInfo = new HashMap<>(3);
        addressInfo.put("address", toViewAddress(hexAddress));
        addressInfo.put("hexAddress", hexAddress);
        addressInfo.put("privateKey", privateKey);
        return addressInfo;
    }

在这个过程中, 涉及到了大量的算法相关的知识, 需要说明的是 tron wallet 的加密算法经过多次转换和加密的, 这个过程非常之复杂, 就不展开讲了。

地址查询

如果我们知道了一个 wallet 地址, 我们可以查询其 wallet 的交易情况, 比如 tron 链上的所有协议, 如 trx 交易、trc20-usdt 交易等等;

String specificWalletTransferUrl = urlAddress + blockWalletBean.monitorAddress + "/transactions/trc20";
Map<String, String> paraMap = new HashMap<>();
paraMap.put("limit", "30");
paraMap.put("only_confirmed", "true");
paraMap.put("contract_address", "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t");
String content = httpGet(specificWalletTransferUrl, paraMap);
System.out.println("content:" + content);
f (!StringUtils.isEmpty(content)) {
    JSONObject jsonObject = JSONObject.parseObject(content);
    JSONArray results = jsonObject.getJSONArray("data");
    //解析数据, 获取 wallet address 交易详细信息

区块扫描

public BigInteger getNowBlock() {
        String url = tronUrl + "/wallet/getnowblock";
        String httpRequest = HttpRequest.get(url).execute().body();
        JSONObject jsonObject1 = JSONObject.parseObject(httpRequest);
        return jsonObject1.getJSONObject("block_header").getJSONObject("raw_data").getBigInteger("number");
    }

写在最后

其实这个 wallet 、智能合约还有很多的功能, 我们经常听到有些人的被盗, 那些被盗的人怎么做到的呢, 我们该如何去防范呢? 这些东西需要我们深入研究才能明白其中的奥秘, 好了篇幅有限, 至此结束。文章来源地址https://www.toymoban.com/news/detail-784681.html

到了这里,关于聊一聊区块链-波场技术, 只聊技术的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 聊一聊 TLS/SSL

    哈喽大家好,我是咸鱼 当我们在上网冲浪的时候,会在浏览器界面顶部看到一个小锁标志,或者网址以 \\\"https://\\\" 开头 这意味着我们正在使用 TLS/SSL 协议进行安全通信。虽然它可能看起来只是一个小小的锁图标和一个 “https” ,但实际上,这个协议在保护我们的在线隐私和安

    2024年02月08日
    浏览(44)
  • 聊一聊AIGC

    “UGC不存在了”——借鉴自《三体》 ChatGPT 的横空出世将一个全新的概念推上风口——AIGC( AI Generated Content)。 GC即创作内容(Generated Content),和传统的UGC、PGC,OGC不同的是,AIGC的创作主体由人变成了人工智能。 xGC PGC:Professionally Generated Content,专业生产内容 UGC:User G

    2024年02月10日
    浏览(53)
  • 聊一聊模板方法模式

    统一抽取,制定规范; 模板方法模式,又叫模板模式,属于23种设计模式中的 行为型模式 。在抽象类中公开定义了执行的方法,子类可以按需重写其方法,但是要以抽象类中定义的方式调用方法。总结起来就是: 定义一个操作的算法结构,而将一些步骤延迟到子类中。在不

    2024年02月04日
    浏览(41)
  • 聊一聊synchronized

    在 Java 中, synchronized 可以用于实现线程同步,有以下几种常见的使用方式: 修饰代码块:将 synchronized 放在代码块的前面, 例如: 在这种方式下,会为给定的对象 obj 获取锁,在代码块执行期间,只有持有该锁的线程才能进入代码块执行。 修饰方法:将 sync

    2024年01月22日
    浏览(50)
  • 聊一聊大模型

    事情还得从ChatGPT说起。 2022年12月OpenAI发布了自然语言生成模型ChatGPT,一个可以基于用户输入文本自动生成回答的人工智能体。它有着赶超人类的自然对话程度以及逆天的学识。一时间引爆了整个人工智能界,各大巨头也纷纷跟进发布了自家的大模型,如:百度-文心一言、科

    2024年02月05日
    浏览(48)
  • 聊一聊适配器模式

    接口不能用?行,我帮你适配 适配器模式(Adapter),是23种设计模式中的 结构型模式 之一;它就像我们电脑上接口不够时,需要用到的拓展坞,起到转接的作用。它可以将新的功能和原先的功能连接起来,使由于需求变动导致不能用的功能,重新利用起来。 上图的Mac上,只

    2024年02月04日
    浏览(43)
  • 聊一聊Vue和Ts

    1 前言 Vue3 已经正式发布了一段时间了,各种生态已经成熟。最近使用 taro+vue3 重构冷链的小程序,经过了一段时间的开发和使用,有了一些自己的思考。 总的来说,Vue3 无论是在底层原理还是在实际开发过程中,都有了很大的进步。 从源码层面来说,使用 Proxy 代替 Object.d

    2023年04月08日
    浏览(62)
  • 聊一聊mysql中的间隙锁

    间隙锁在mysql中经常使用到,今天就聊一聊mysql的间隙锁的内容。 间隙锁是为了解决幻读的问题,并且在当前读的场景下解决的。 当前读包含:update,delete,insert,select…lock in share mode,select…for update 一基本概念 1、行锁:给某一行进行加锁 2、间隙锁:两个值之间的间隙,为解

    2024年02月12日
    浏览(31)
  • 聊一聊Java抽象同步队列AQS

    AQS是锁的底层支持 由该图可以看到,AQS是一个FIFO的双向队列,其内部通过节点head和tail记录队首和队尾元素,队列元素的类型为Node。其中Node中的thread变量用来存放进入AQS队列里面的线程;Node节点内部的SHARED用来标记该线程是获取共享资源时被阻塞挂起后放入AQS队列的,EX

    2024年02月16日
    浏览(35)
  • 聊一聊nginx中KeepAlive的设置

    之前工作中遇到一个KeepAlive的问题,现在把它记录下来,场景是这样的: 从上图可以看出,用户通过Client访问的是LVS的VIP, VIP后端挂载的RealServer是Nginx服务器。 Client可以是浏览器也可以是一个客户端程序。一般情况下, 这种架构不会出现问题,但是如果Client端把请求发送给

    2024年02月01日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包