您现在的位置:主页 > 一品轩高手论坛981234 >

ELISUN-ETH交易部分分析

文章来源:本站原创 发布时间:2019-09-08 点击数:

  ELISUN前言,这个 atomic 是 go 语言的一个包 sync/atomic,用来实现原子操作。ELISUN发现在这个结构体中, data 为数据字段,其余三个为缓存。下面是计算hash的函数:

  计算哈希前,首先会从缓存 tx.hash 中获取,如果取到,则直接返回值。没有,则使用rlpHash 计算:

  Transaction 中,data 为 txdata 类型的,定义于同文件中,里面详细规定了交易的具体字段:

  AccountNonce:此交易的发送者已发送过的交易数(可防止重放攻击)

  Recipient:交易的接收者地址,如果这个字段为 nil 的话,则这个交易为“合约创建”类型交易

  我们会发现,交易中没有包含发送者地址这条数据,这是因为这个地址已包含在签名信息中,后面我们会分析到相关代码,另外,以太坊节点还会提供 JSON RPC 服务,供外部调用来传输数据。传输的数据格式为 json,武汉大学平面设计研究生。因此,本文件中,还定义了交易的 json 类型数据结构,以及相关的转换函数。

  对于每个传入的区块,该函数会读取块中的每一条交易来分别处理。首先建立条目(entry),数据类型为:txLookupEntry。内容包括区块哈希、区块号以及交易索引(交易 在区块中的位置),然后将此 entry 进行 rlp 编码作为存入数据库的 value。key 部分与区块存储类似,组成结构为交易前缀+交易哈希。

  在源码中交易只有一种数据结构,如果非要给交易分个类的话,我认为交易可以分为三种:转账的交易、创建合约的交易、执行合约的交易。web3.js 提供了发送交易的接口:

  参数是一个对象,如果在发送交易的时候指定不同的字段,区块链节点就可以识别出对应类型的交易。

  转账是最简单的一种交易,这里转账是指从一个账户向另一个账户发送以太币。发送转账交易的时候只需要指定交易的发送者、接收者、转币的数量。使用 web3.js 发送转账交易应该像这样:

  value 是转移的以太币数量,单位是 wei,对应的是源码中的 Amount 字段。to 对应的是源码中的 Recipient

  创建合约指的是将合约部署到区块链上,这也是通过发送交易来实现。在创建合约的交易中,to 字段要留空不填,在 data 字段中指定合约的二进制代码,from 字段是交易的发送者也是合约的创建者。

  调用合约中的方法,需要将交易的 to 字段指定为要调用的合约的地址,通过 data 字段指定要调用的方法以及向该方法传递的参数。

  data 字段需要特殊的编码规则,具体细节可以参考 Ethereum Contract ABI(自己拼接字段既不方便又容易出错,所以一般都使用封装好的 SDK(比如 web3.js) 来调用合约)。

  按照以太坊架构设计,交易的执行可大致分为内外两层结构:第一层是虚拟机外,包括执行前将 Transaction 类型转化成 Message,创建虚拟机(EVM)对象,计算一些 Gas 消耗,以及执行交易完毕后创建收据(Receipt)对象并返回等;第二层是虚拟机内,包括执行 转帐,和创建合约并执行合约的指令数组。

  Receipt 中有一个 Log 类型的数组,其中每一个 Log 对象记录了 Tx 中一小步的操作。所以,每一个 tx 的执行结果,由一个 Receipt 对象来表示;更详细的内容,由一组 Log 对象来记录。这个 Log 数组很重要,比如在不同 Ethereum 节点(Node)的相互同步过程中, 待同步区块的 Log 数组有助于验证同步中收到的 block 是否正确和完整,所以会被单独同步(传输)。

  GasPool 对象是在一个 Block 执行开始时创建,并在该 Block 内所有 tx 的执行过程中共享,对于一个 tx 的执行可视为“全局”存储对象; Message 由此次待执行的 tx 对象转化而来,并携带了解析出的 tx 的(转帐)转出方地址,属于待处理的数据对象;EVM 作为Ethereum 世界里的虚拟机(Virtual Machine),作为此次 tx 的实际执行者,完成转帐和合约(Contract)的相关操作。

  偿退 Gas。它包括两个部分:首先将剩余 st.gas 折算成 Ether,归还给交易的(转帐)转出方账户;然后,基于实际消耗量 requiredGas,系统提供一定的补偿,数量为 refundGas。refundGas 所折算的 Ether 会被立即加在(转帐)转出方账户上, 同时 st.gas += refundGas,gp += st.gas,即剩余的 Gas 加上系统补偿的 Gas,被一起归并进 GasPool,供之后的交易执行使用。

  奖励所属区块的挖掘者:系统给所属区块的作者,亦即挖掘者账户,增加一笔金额,数额等于 st.data,Price * (st.initialGas – st.gas)。注意,这里的 st.gas 在步骤 5 中被加上了 refundGas, 所以这笔奖励金所对应的 Gas,其数量小于该交易实际消耗量 requiredGas。

  由上可见,除了步骤 3 中 EVM 函数的执行,其他每个步骤都在围绕着 Gas 消耗量作文章。

  步骤 5 的偿退机制很有意思,设立它的目的何在?目前为止我只能理解它可以避免交易执行过程中过快消耗 Gas,至于对其全面准确的理解尚需时日。

  Ethereum 中每个交易(transaction,tx)对象在被放进 block 时,都是经过数字签名的, 这样可以在后续传输和处理中随时验证 tx 是否经过篡改。Ethereum 采用的数字签名是椭圆曲线数字签名算法(Elliptic Cure Digital Signature Algorithm,ECDSA)。ECDSA 相比于基于大质数分解的 RSA 数字签名算法,可以在提供相同安全级别(in bits)的同时,仅需更短的公钥(public key)。这里需要特别留意的是,tx 的转帐转出方(发送方)地址,就是对该 tx 对象作 ECDSA 签名计算时所用的公钥 publicKey。

  当需要恢复出 tx 对象的转帐转出方地址时(比如在需要执行该交易时),Ethereum 会先从 tx 的 signature 中恢复出公钥,再将公钥转化成一个 common.Address 类型的地址,signature 由 tx 对象的三个成员变量 R,S,V 转化成字节数组[]byte 后拼接得到。

  Sender()函数体中,signer.Sender()会从本次数字签名的签名字符串(signature)中恢复出公钥,并转化为 tx 的(转帐)转出方地址。此函数最终会调用同文件下的 recoverPlain 函数来进行恢复

  注意,EVM 中定义的成员变量 Context 和 StateDB, 仅仅声明了变量名而无类型,而变量名同时又是其类型名,在 Golang 中,这种方式意味着宗主结构体可以直接调用该成员变量的所有方法和成员变量,比如 EVM 调用 Context 中的 Transfer()。

  交易的转帐操作由 Context 对象中的 TransferFunc 类型函数来实现,类似的函数类型,还有 CanTransferFunc, 和 GetHashFunc。这三个类型的函数变量 CanTransfer, Transfer, GetHash,在 Context 初始化时从外部传入,目前使用的均是一个本地实现。可见目前的转帐函数 Transfer()的逻辑非常简单,转帐的转出账户减掉一笔以太币,转入账户加上一笔以太币。由于 EVM 调用的 Transfer()函数实现完全由 Context 提供,所以,假设如果基于 Ethereum 平台开发,需要设计一种全新的“转帐”模式,那么只需写一个新的 Transfer()函数实现,在 Context 初始化时赋值即可。

  有朋友或许会问,这里 Transfer()函数中对转出和转入账户的操作会立即生效么?万一两步操作之间有错误发生怎么办?答案是不会立即生效。StateDB 并不是真正的数据库, 只是一行为类似数据库的结构体。它在内部以 Trie 的数据结构来管理各个基于地址的账 户,可以理解成一个 cache;当该账户的信息有变化时,变化先存储在 Trie 中。仅当整个Block 要被插入到 BlockChain 时,StateDB 里缓存的所有账户的所有改动,才会被真正的提交到底层数据库。ETH买卖部分剖析

  这个 atomic 是 go 言语的一个包 sync/atomic,用来完结原子操作。在这个结构体中, data 为数据字段,其他三个为缓存。下面是核算hash的函数:

  核算哈希前,首要会从缓存 tx.hash 中获取,假如取到,则直接回来值。没有,则运用rlpHash 核算:

  Transaction 中,data 为 txdata 类型的,界说于同文件中,里边详细规矩了买卖的详细字段:

  AccountNonce:此买卖的发送者已发送过的买卖数(可防止重放进犯)

  Recipient:买卖的接收者地址,假如这个字段为 nil 的话,则这个买卖为“合约创立”类型买卖

  咱们会发现,买卖中没有包含发送者地址这条数据,这是因为这个地址已包含在签名信息中,后边咱们会剖析到相关代码,别的,以太坊节点还会供给 JSON RPC 服务,供外部调用来传输数据。传输的数据格局为 json,因而,本文件中,还界说了买卖的 json 类型数据结构,以及相关的转化函数。

  关于每个传入的区块,该函数会读取块中的每一条买卖来别离处理。首要树立条目(entry),数据类型为:txLookupEntry。内容包含区块哈希、区块号以及买卖索引(买卖 在区块中的方位),然后将此 entry 进行 rlp 编码作为存入数据库的 value。key 部分与区块存储相似,组成结构为买卖前缀+买卖哈希。

  在源码中买卖只要一种数据结构,假如非要给买卖分个类的话,我以为买卖能够分为三种:转账的买卖、创立合约的买卖、履行合约的买卖。web3.js 供给了发送买卖的接口:

  参数是一个目标,假如在发送买卖的时分指定不同的字段,区块链节点就能够识别出对应类型的买卖。

  转账是最简略的一种买卖,这儿转账是指从一个账户向另一个账户发送以太币。发送转账买卖的时分只需求指定买卖的发送者、接收者、转币的数量。运用 web3.js 发送转账买卖应该像这样:

  value 是搬运的以太币数量,单位是 wei,对应的是源码中的 Amount 字段。to 对应的是源码中的 Recipient

  创立合约指的是将合约布置到区块链上,这也是通过发送买卖来完结。在创立合约的买卖中,to 字段要留空不填,在 data 字段中指定合约的二进制代码,from 字段是买卖的发送者也是合约的创立者。

  调用合约中的办法,需求将买卖的 to 字段指定为要调用的合约的地址,通过 data 字段指定要调用的办法以及向该办法传递的参数。

  data 字段需求特别的编码规矩,详细细节能够参阅 Ethereum Contract ABI(自己拼接字段既不便利又简略犯错,所以一般都运用封装好的 SDK(比方 web3.js) 来调用合约)。

  依照以太坊架构规划,买卖的履行可大致分为表里两层结构:第一层是虚拟机外,包含履行前将 Transaction 类型转化成 Message,创立虚拟机(EVM)目标,核算一些 Gas 耗费,以及履行买卖结束后创立收据(Receipt)目标并回来等;第二层是虚拟机内,包含履行 转帐,和创立合约并履行合约的指令数组。

  Receipt 中有一个 Log 类型的数组,其间每一个 Log 目标记载了 Tx 中一小步的操作。所以,每一个 tx 的履行成果,由一个 Receipt 目标来表明;更详细的内容,由一组 Log 目标来记载。这个 Log 数组很重要,比方在不同 Ethereum 节点(Node)的彼此同步进程中, 待同步区块的 Log 数组有助于验证同步中收到的 block 是否正确和完好,所以会被独自同步(传输)。

  GasPool 目标是在一个 Block 履行开始时创立,并在该 Block 内一切 tx 的履行进程中同享,关于一个 tx 的履行可视为“大局”存储目标; Message 由此次待履行的 tx 目标转化而来,并带着了解分出的 tx 的(转帐)转出方地址,归于待处理的数据目标;EVM 作为Ethereum 国际里的虚拟机(Virtual Machine),作为此次 tx 的实践履行者,完结转帐和合约(Contract)的相关操作。

  偿退 Gas。它包含两个部分:首要将剩下 st.gas 折算成 Ether,归还给买卖的(转帐)转出方账户;然后,根据实践耗费量 requiredGas,体系供给必定的补偿,数量为 refundGas。refundGas 所折算的 Ether 会被当即加在(转帐)转出方账户上, 一同 st.gas += refundGas,gp += st.gas,即剩下的 Gas 加上体系补偿的 Gas,被一同归并进 GasPool,供之后的买卖履行运用。

  奖赏所属区块的发掘者:体系给所属区块的作者,亦即发掘者账户,添加一笔金额,数额等于 st.data,Price * (st.initialGas – st.gas)。留心,这儿的 st.gas 在进程 5 中被加上了 refundGas, 所以这笔奖赏金所对应的 Gas,其数量小于该买卖实践耗费量 requiredGas。

  由上可见,除了进程 3 中 EVM 函数的履行,其他每个进程都在围绕着 Gas 耗费量作文章。

  进程 5 的偿退机制很有意思,建立它的意图安在?现在为止我只能了解它能够避免买卖履行进程中过快耗费 Gas,至于对其全面精确的了解需求时日。

  Ethereum 中每个买卖(transaction,tx)目标在被放进 block 时,都是通过数字签名的, 这样能够在后续传输和处理中随时验证 tx 是否通过篡改。Ethereum 选用的数字签名是椭圆曲线数字签名算法(Elliptic Cure Digital Signature Algorithm,ECDSA)。ECDSA 比较于根据大质数分化的 RSA 数字签名算法,能够在供给相同安全级别(in bits)的一同,仅需更短的公钥(public key)。这儿需求特别留心的是,tx 的转帐转出方(发送方)地址,便是对该 tx 目标作 ECDSA 签名核算时所用的公钥 publicKey。

  当需求康复出 tx 目标的转帐转出方地址时(比方在需求履行该买卖时),Ethereum 会先从 tx 的 signature 中康复出公钥,再将公钥转化成一个 common.Address 类型的地址,signature 由 tx 目标的三个成员变量 R,S,V 转化成字节数组[]byte 后拼接得到。

  Sender()函数体中,signer.Sender()会从本次数字签名的签名字符串(signature)中康复出公钥,并转化为 tx 的(转帐)转出方地址。此函数终究会调用同文件下的 recoverPlain 函数来进行康复

  留心,EVM 中界说的成员变量 Context 和 StateDB, 仅仅声明晰变量名而无类型,而变量名一同又是其类型名,在 Golang 中,这种办法意味着宗主结构体能够直接调用该成员变量的一切办法和成员变量,比方 EVM 调用 Context 中的 Transfer()。

  买卖的转帐操作由 Context 目标中的 TransferFunc 类型函数来完结,相似的函数类型,还有 CanTransferFunc, 和 GetHashFunc。这三个类型的函数变量 CanTransfer, Transfer, GetHash,在 Context 初始化时从外部传入,现在运用的均是一个本地完结。可见现在的转帐函数 Transfer()的逻辑十分简略,转帐的转出账户减掉一笔以太币,转入账户加上一笔以太币。因为 EVM 调用的 Transfer()函数完结彻底由 Context 供给,所以,假定假如根据 Ethereum 渠道开发,需求规划一种全新的“转帐”形式,那么只需写一个新的 Transfer()函数完结,在 Context 初始化时赋值即可。

  有朋友或许会问,这儿 Transfer()函数中对转出和转入账户的操作会当即收效么?如果两步操作之间有过错发作怎么办?答案是不会当即收效。StateDB 并不是真实的数据库, 仅仅一行为相似数据库的结构体。它在内部以 Trie 的数据结构来办理各个根据地址的账 户,能够了解成一个 cache;当该账户的信息有改变时,改变先存储在 Trie 中。仅当整个Block 要被刺进到 BlockChain 时,StateDB 里缓存的一切账户的一切改动,才会被真实的提交究竟层数据库。

  合约(Contract)是 EVM 用来履行(虚拟机)指令的结构体。Contract 的结构界说于:core/vm/contract.go 中,在这些成员变量里,caller 是转帐转出方地址(账户),self 是转入方地址,不过它们的类型都用接口 ContractRef 来表明;Code 是指令数组,其间每一个 byte 都对应于一个预界说的虚拟机指令;CodeHash 是 Code 的 RLP 哈希值;Input 是数据数组,是指令所操作的数据调集;Args 是参数。

  有意思的是 self 这个变量,为什么转入方地址要被命名成 self 呢? Contract 完结了ContractRef 接口,回来的恰恰便是这个 self 地址。

  合约(Contract)是 EVM 用来执行(虚拟机)指令的结构体。Contract 的结构定义于:core/vm/contract.go 中,在这些成员变量里,caller 是转帐转出方地址(账户),self 是转入方地址,不过它们的类型都用接口 ContractRef 来表示;Code 是指令数组,其中每一个 byte 都对应于一个预定义的虚拟机指令;CodeHash 是 Code 的 RLP 哈希值;Input 是数据数组,是指令所操作的数据集合;Args 是参数。

  有意思的是 self 这个变量,为什么转入方地址要被命名成 self 呢? Contract 实现了ContractRef 接口,返回的恰恰就是这个 self 地址。

玄机图| 牛魔王论坛| 05666有钱人高手| 开奖现场| 平码三中三| 金多宝心水论坛| 香港神算子中特| 九龙老牌图库| 品特轩www555939| 114888红姐心水论| 玄机图| 白小姐马会| 小鱼儿玄机2站资料| 刘伯温开奖| 发财报彩图| 藏宝图| 马会论坛| 香港管家婆| 168开奖下载| 118图库|