Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
98 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3. p' i; o) S! Z: d
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');
7 Q; a, M# A, l6 zvar web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));, i) O  r( H2 l& {
var util = require('ethereumjs-util');
4 C$ D* W4 X3 k5 ]& I' Y( Nvar tx = require('ethereumjs-tx');# W7 V$ |" l' R  K2 e
首先我们从理解一个私钥开始。以太坊通过
# Y+ [9 j; i( y8 Z7 m8 d6 X& M公钥加密
" }" [0 d( a6 X, h1 Y进行授权。具体来说,用
& q" O- R+ }' f( Z* n7 Y椭圆曲线数字加密算法2 P( n2 e  U) t$ ?1 {
,通过. I5 e+ q9 Q5 _
secp256k1
; O4 y/ v" G& ?$ |. r0 @7 d标准生成公钥。除了有一些6 C) J  q) s6 |
限制
$ Z$ `" X# t. y% ]/ r1 R外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';
; b) \3 R+ V* G9 `4 w通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));
* _/ A# P& E7 [% G* n* D* Z& Y, S如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27
0 O4 C# p! a* a5 V; P* U, I与私钥相关联的以太坊地址是用相应公钥进行
/ b* K" P" z" `3 {, SSHA3-256 (Keccak)8 d. N3 P* }" f2 P) L7 ]
哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);6 R7 v% f  L2 \$ {; z/ V+ ~& m* Y, y
//0x53ae893e4b22d707943299a8d0c844df0e3d5557# G6 }) E% x2 w; ~) B" X) f/ M
正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:- i6 l) G+ ~0 o: s1 M
nonce:输出交易的次数,从 0 开始
$ a& }* T  O8 V: g; s8 D( X! G/ Nbalance:账户中的以太币数
# B6 c2 U  c5 v1 P( JstorageRoot:与账户存储相关联的哈希值; @/ Q) H' x9 V3 N; f
codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制' |' y6 {- u6 t- f8 v! P0 k% c) `: I
接下来我们看一下交易,交易有 6 个输入域:
2 _  R9 A% e4 x* H9 l% B7 anonce:输出交易的次数,从 0 开始
# K7 P  f/ \8 HgasPrice:交易中花费的单位 Gas 的价格
4 N; L" B( u! S3 C/ ]gasLimit:处理交易允许花费的最大 Gas 量' Y$ g2 {3 h  w9 A7 A
to:交易发送到的账户,如果是空,交易就会创建合约7 c7 S9 Z4 V, D( e3 R
value:发送的以太币的量% _: _% l& U3 q6 B6 [- ^
data:可以是任意的消息或合约函数调用或创建合约的代码. l. ]4 R" h8 U$ ~( x! J3 m7 u
一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {
0 G: q0 N/ s5 u# [    nonce: web3.toHex(0),
  ~6 T& b8 y9 @6 H7 P' h    gasPrice: web3.toHex(20000000000),
2 J# D; n/ H; A7 ]1 z6 }    gasLimit: web3.toHex(100000),
! H5 `1 M4 K) r4 @) V1 e    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
% y+ t% Z* s; u2 Y1 o9 z1 s* g    value: web3.toHex(1000)," {+ Z, S) B# e# L2 o
    data: '0xc0de'/ B3 ]+ ^! ^$ o$ Q% C( r, P
};4 u' ~' N5 O4 G: O
注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');, \2 ?7 |% W! t' i% Z2 I
var transaction = new tx(rawTx);
4 H( N$ K# g6 h% A& itransaction.sign(p);
- d# T% I& a- m' h2 X5 L然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
" t% {- l" c$ wEtherscan
. [: M, i' c# R" |, X中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
9 ]# S& m1 G, \) y) E: [4 h//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662* L5 d  j2 @0 M- v1 Z
接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);, o3 O# z3 K, e5 u5 L9 d
//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff7 g$ M8 |! B3 _$ r5 V
为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));
$ `3 v) o0 ^: h8 ]9 ~//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b# x) S7 _& G$ v) s9 e; u# V
接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e5 l  y% `3 ~! z8 ]8 z# r. L! I
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff5 Y, N. Q! y$ y* w) \& A
接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
% U; L' P5 V3 `! t% F# X- \; e' n//0x950041c1599529a9f64cf2be59ffb86072f001116 ~8 A3 W& l  g+ X: P
合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');4 X9 P" V. h- u6 O+ C) i7 f! B
console.log(contractTx.from);
5 }: c& ^/ L0 p8 J: F3 S5 p//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f- Q2 m# J. B7 k1 f) ?
console.log(contractTx.nonce);; o+ A$ b$ u* X  Z
//0
9 N- ]) m6 h7 S2 U所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));9 n" @& X4 @- K* u, z$ o
//0x950041c1599529a9f64cf2be59ffb86072f00111
+ w3 J; x: H; J; Q4 H; s' V  M现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站( ?8 F/ p5 U% m0 ^+ m2 C4 ]
https://www.ethereum.org/! Q; s( ^& j  _
以太坊的其中一个客户端 Mist 的 GitHub Repo6 a8 B# Q" B; ^2 d, n
https://github.com/ethereum/mist/releases
$ E1 W9 `8 I' U. X5 q/ A" R! HSolidity. [; P0 T* f8 F& `( j
http://solidity.readthedocs.io/en/latest/
5 e# B+ k( R7 C- g- A. ]Web3 api
) g& y4 }/ W! `9 |0 p& \/ Q( dhttps://github.com/ethereum/wiki/wiki/JavaScript-API
) w% r1 ^2 H# a/ G9 Y- ^+ y社区讨论
& V" A" d# A1 }/ w$ ehttps://www.reddit.com/r/ethereum/0 N- ?8 T* K+ g. P: H0 H: i
如果你有任何关于此文的问题,你可以在我们/ S( E9 |) V3 \% `7 M
GitHub nightlyHacks repo  p' |7 `0 b# b4 k) s; C! ^$ O0 e1 B
中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14