Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

从记录跟踪交易探索以太坊交易

V刘晨曦
99 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3; P5 q. I) R( D+ B7 v4 J( N
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');3 h7 g+ o! s: h
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
* r/ T2 P  y: w* X) J$ qvar util = require('ethereumjs-util');5 b8 i* n4 _( a: {9 B" Y
var tx = require('ethereumjs-tx');
* ~7 w& G7 y$ b6 V' {0 w. q首先我们从理解一个私钥开始。以太坊通过- [" Z7 n% @! u( B  j
公钥加密
1 x  \3 T" ~1 A* a7 m( v进行授权。具体来说,用
6 Z( G+ T7 O9 v1 V* G& [/ s椭圆曲线数字加密算法, \5 A' A" N1 S6 z
,通过
1 J0 j/ @8 _8 C0 n3 _: qsecp256k1# F; |* s8 ]+ z
标准生成公钥。除了有一些% g% u- s, _' d8 Y% V9 N8 h& t
限制& S5 F5 b, S$ s  K8 P2 C
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';/ d- v& E6 y, V( p
通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));
4 T% ]9 N% F# V- B5 W$ z如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27+ y4 }; a" ~% |0 q1 D. Y8 e. |4 y
与私钥相关联的以太坊地址是用相应公钥进行1 _% @- W+ G; K
SHA3-256 (Keccak)3 A+ A- `; ?2 k8 o# E
哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
+ j- ~& H" l5 t' s+ e* B* p//0x53ae893e4b22d707943299a8d0c844df0e3d5557& p0 _; q: Z8 c1 V
正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:4 b+ q9 ]/ [0 U9 S
nonce:输出交易的次数,从 0 开始
# {, V2 Y8 B! v5 M# i; ybalance:账户中的以太币数
  ~7 P, _& f( I& v. zstorageRoot:与账户存储相关联的哈希值8 S% y7 @4 P% _2 _) A1 \& e, q/ n
codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
; V) c# p+ X) p+ a接下来我们看一下交易,交易有 6 个输入域:; |% R9 A0 k0 D
nonce:输出交易的次数,从 0 开始5 W: p& b8 m: {; `3 o: w: i
gasPrice:交易中花费的单位 Gas 的价格0 C& \( p: J% g! b& z
gasLimit:处理交易允许花费的最大 Gas 量7 T+ a2 z9 \' F+ S- t) G
to:交易发送到的账户,如果是空,交易就会创建合约
) E& e6 Q. U; J" |4 Fvalue:发送的以太币的量) ?4 Q9 F8 V- Z
data:可以是任意的消息或合约函数调用或创建合约的代码
9 y+ z8 b$ Z8 n9 N" B2 Q, z一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {+ O# b1 q  ]% N
    nonce: web3.toHex(0),
) s- y+ O' l' ~+ F    gasPrice: web3.toHex(20000000000),
0 F+ Q0 _# s: n* ~& V" w+ g    gasLimit: web3.toHex(100000),
; a) K  A1 F, M    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',0 Q8 @8 L3 R% h+ P6 L- m
    value: web3.toHex(1000),
4 T5 ^9 p; c) }4 m! R$ W    data: '0xc0de'
* Y$ D" |( }; v4 {};
. u. a& M8 t9 ?7 M, h0 @4 T! m注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');- n8 j( J! H1 w( q( ?+ n1 b: G
var transaction = new tx(rawTx);
/ \+ n- {% H% l: wtransaction.sign(p);
4 P6 @/ }4 Q, E$ ]. d  T然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
% L1 p: l8 B5 K2 _! H# mEtherscan7 S& a* t- i. g- |( d" S
中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
& z4 E5 \4 _# [) [1 P! j: ?//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
' Y* B& P  ~. C, ]( D8 F接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);" c5 K, G' X- B) e# F
//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
7 I$ j- {' D/ [为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));, q7 l; Q4 k+ C0 n# S1 F
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
. C6 L( Q, c; l1 l+ l. v接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e+ x- E: [4 R! X; g# @! q( }
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff+ s8 _' B& j6 H, I0 ~
接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
* U6 O! m7 Z, ~! A5 L: ^# e1 @; N; F//0x950041c1599529a9f64cf2be59ffb86072f00111
6 Y2 S6 ?' n  N0 M6 o/ Y合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');+ q! ]& \7 Q/ ?1 l- r# ^5 z# ~
console.log(contractTx.from);5 G; w7 Y7 L/ R& u$ O) N
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f- o9 u% W5 a/ r0 h- C% k) [
console.log(contractTx.nonce);- ?) g$ o% T* x+ g% R7 Y
//04 \9 b1 Z; @. ?5 Y/ m7 q/ D
所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));
; G" H: k9 |6 W//0x950041c1599529a9f64cf2be59ffb86072f00111
5 S6 {4 M& V+ d) B7 x( C. t现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站
7 Q" c* [2 a& k2 A. O* G9 L% C- ohttps://www.ethereum.org/) q  [9 m+ _2 w6 ~
以太坊的其中一个客户端 Mist 的 GitHub Repo
& p$ q! [. G5 G+ h; G( D8 ehttps://github.com/ethereum/mist/releases
; C) ?7 v+ Y+ @/ W5 k; zSolidity
" U3 ^% u$ a* f6 W9 N- B8 J2 `http://solidity.readthedocs.io/en/latest/
4 V* H/ D; r" U* JWeb3 api
+ }' o! J5 X/ M+ f: Shttps://github.com/ethereum/wiki/wiki/JavaScript-API
3 G6 U3 ^5 V; T% g, q! z7 I社区讨论
; E' }8 W' o# r' T2 khttps://www.reddit.com/r/ethereum/6 b! b; V. G8 L0 Y6 k/ X3 ^! @
如果你有任何关于此文的问题,你可以在我们! O" }0 m. S$ @+ B( f
GitHub nightlyHacks repo
" }7 a/ a+ ^. l" @8 t4 b中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14