Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
144 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.34 J6 p% f% C: G) o
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');0 }+ i& T4 @4 W0 y$ W$ F1 h
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
0 a! a* l$ j3 f  x( o0 e, Xvar util = require('ethereumjs-util');9 C: Y( f. i2 v
var tx = require('ethereumjs-tx');
/ E& Q3 H5 \# f首先我们从理解一个私钥开始。以太坊通过
* p* m1 R; s5 p# }0 I公钥加密
5 |( L. Q3 s" j' Z5 y2 \* ?进行授权。具体来说,用
) j, m- k! G; _椭圆曲线数字加密算法
" g6 B/ _, p0 W, K8 O,通过
) [  h4 R$ n9 M/ |secp256k15 Z0 \1 ^0 r$ u" x
标准生成公钥。除了有一些
6 y6 ~$ Y0 z2 `8 [/ D7 f限制* y0 |" S. k) a4 T! F& k0 k: r
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';% j* k6 e) W& W/ H
通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));
6 @# H2 W0 I) j+ i; p如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b273 G$ O9 C' t6 g; O8 ^$ g
与私钥相关联的以太坊地址是用相应公钥进行$ W. V0 J: J9 `4 B2 Z, |; V# M
SHA3-256 (Keccak)- l- V6 m/ u% d
哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
; a" y' T$ X5 f8 ^8 P' F/ s. _8 l//0x53ae893e4b22d707943299a8d0c844df0e3d5557
2 A, g* F; H4 ?* E' \5 `& c- Y正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:
4 `1 d$ V# n3 v& W8 Nnonce:输出交易的次数,从 0 开始
5 p5 f" h" p# G3 Abalance:账户中的以太币数) q" ]* K  Y2 G+ B: ~- V4 }5 g
storageRoot:与账户存储相关联的哈希值' B& T8 v2 D! z
codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
- F* G  V! j6 F1 y接下来我们看一下交易,交易有 6 个输入域:
' ]1 T3 l) U. b) Tnonce:输出交易的次数,从 0 开始" M! c3 u$ e; K# A) n$ X
gasPrice:交易中花费的单位 Gas 的价格/ u* V" q3 n0 X
gasLimit:处理交易允许花费的最大 Gas 量
# u" t( e6 J$ b$ n2 [0 Zto:交易发送到的账户,如果是空,交易就会创建合约4 S/ x; ?& z: r+ c- d) ^7 ^
value:发送的以太币的量, H" T6 m1 A) k' s+ z  I! n" u  D  ?' e
data:可以是任意的消息或合约函数调用或创建合约的代码9 i' h2 v4 _: }5 N7 n
一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {
( N" Z6 W" B3 B& u  Q    nonce: web3.toHex(0),
7 n8 x. f; c7 p" r    gasPrice: web3.toHex(20000000000),
$ s6 s. a6 C7 }! z9 Z5 l: [8 ?    gasLimit: web3.toHex(100000),
5 M) L- I; c2 G- r" E. S    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
) m, Y. @$ u$ Q) m5 Y0 N    value: web3.toHex(1000),
4 y6 Z" s5 \2 ^9 D  J' c    data: '0xc0de'
6 @4 R8 p1 o' _9 R};
6 J; R$ i" e* @  {3 v! T注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');5 e+ y$ @" a+ x1 T/ Y
var transaction = new tx(rawTx);7 S5 P# }3 x; V% R) Y$ v9 J: f# N
transaction.sign(p);, x1 e$ ]3 J9 h5 b' S* j
然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在4 O& W$ }( l( F% O3 q
Etherscan
% f4 [# y5 C5 n3 l# y+ d3 l中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
: m0 b8 P3 D/ q# Y+ z//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662- A/ B2 ?9 y6 o+ y
接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
( I. C( r; }, V" Q//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff: e6 o% E7 N; d8 i9 w3 d' b9 ~" a
为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));8 q# ~' A) n" T: V1 S! H
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b: s$ P# [0 Q0 m, ]
接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e
3 p0 Y, m2 v2 |* {8 yuint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff4 T0 `( k, P6 r8 Z# ^; q! G3 |
接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);* X; ~5 x% ?. x- y; _
//0x950041c1599529a9f64cf2be59ffb86072f00111
- K8 x4 ?' M. n; t1 R- L2 {合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
; V8 R! ?/ A0 B3 x4 L' r0 bconsole.log(contractTx.from);) w. ~) D! a: `3 l4 x. Q' M1 k1 y: P
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
7 @! H3 ~& q- }& gconsole.log(contractTx.nonce);- S5 Z& A( i2 }  }, N# M, u
//0
6 J, ?( ~7 E2 B$ R9 f3 b) y. p所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));- ~: b  H& A2 w$ t" o; b
//0x950041c1599529a9f64cf2be59ffb86072f00111" V. h# g# Y" d2 F- X
现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站8 m7 {( w8 U* p0 a% D) r
https://www.ethereum.org/4 L, ?6 Y! l- C9 u: w- G$ R
以太坊的其中一个客户端 Mist 的 GitHub Repo
  a5 i/ p2 _" D6 r! Ehttps://github.com/ethereum/mist/releases
+ ^' h8 z8 ?% _3 K, T! R$ kSolidity
: I" T( G/ Q6 n+ c, r# [http://solidity.readthedocs.io/en/latest/6 ]' l0 x1 w! g# r$ k
Web3 api
8 y4 c4 p, a& n$ ]! e5 Zhttps://github.com/ethereum/wiki/wiki/JavaScript-API
, p$ N3 i, N/ ^3 @; [" T社区讨论2 i5 V, s' {8 j; E
https://www.reddit.com/r/ethereum/+ T# Z+ O3 }( X# h
如果你有任何关于此文的问题,你可以在我们: X: w$ ^& D9 n+ k2 ]5 T! _; h
GitHub nightlyHacks repo
2 L+ y" \4 y" J0 ]8 |4 J2 U4 K中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14