Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
112 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3$ E: ^9 g0 i6 D+ Y$ q; a% ?" ~6 N; x
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');6 v* [9 r+ o0 W' D2 g
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));9 P  T4 ^" y; _: W: w0 n/ O  {
var util = require('ethereumjs-util');
  s6 c: b# G5 |8 m# t/ dvar tx = require('ethereumjs-tx');+ i6 B% ~( H: f
首先我们从理解一个私钥开始。以太坊通过
/ E# D: A* [) R: X" ^1 ?公钥加密. c. j  a2 E% c6 V; w. p
进行授权。具体来说,用
/ f$ t" v5 M3 G椭圆曲线数字加密算法# i5 b1 m; @* y* `' c* t) t7 u
,通过. C( H- z& a" M" E* a
secp256k1! o& O4 R, Z; b, G6 x$ L
标准生成公钥。除了有一些
/ z/ F/ o2 l; B  m( n限制
+ b% o# B+ `8 q) x7 ~- _& B; j+ @外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';
& @8 O0 _/ c& k& k. m" E. O7 P通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));/ Z6 p# N/ B+ v. }' U
如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27
1 f) t' Q& o( h1 S( {与私钥相关联的以太坊地址是用相应公钥进行" @4 _# G3 R2 X4 |! V. e
SHA3-256 (Keccak)
! c( R7 U  E( ^: j哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
$ O) `" c9 B7 u//0x53ae893e4b22d707943299a8d0c844df0e3d5557
# i2 i$ d/ n9 c7 V正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:
7 d$ v: I6 K2 a$ @! M% x" enonce:输出交易的次数,从 0 开始4 A+ V. l" x1 f
balance:账户中的以太币数8 |/ s8 \2 @- c7 ~) ^- Q
storageRoot:与账户存储相关联的哈希值! ~) X. b- |, w% H0 d, Q; N6 z+ A
codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
* m% q4 D. S2 g6 S接下来我们看一下交易,交易有 6 个输入域:
( ^8 T9 q- c; j% F9 P* ]7 Jnonce:输出交易的次数,从 0 开始
, e9 ?) d) _* U& fgasPrice:交易中花费的单位 Gas 的价格
$ L" z* ?* J4 vgasLimit:处理交易允许花费的最大 Gas 量
% ?8 s3 j9 M' E" q, Qto:交易发送到的账户,如果是空,交易就会创建合约5 k2 T  Q3 ?: K: B2 |
value:发送的以太币的量
% h6 b; G% c0 B2 L# ]' D1 Edata:可以是任意的消息或合约函数调用或创建合约的代码7 `5 |0 }# \3 I+ R/ z* Q
一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {
( t8 W; Z, I  O    nonce: web3.toHex(0),
( R2 T3 y3 g8 l1 C    gasPrice: web3.toHex(20000000000),  k" z' a3 i- z% j9 m4 ]2 H
    gasLimit: web3.toHex(100000),
: Q! W0 r5 ?1 f& S% k1 e1 O    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
& c$ v# |/ `: a    value: web3.toHex(1000),
( R$ P  h! l2 E9 X( s+ W    data: '0xc0de': s3 h, T$ \: |7 h0 K. f
};
; b- i# l4 v+ |' L8 O注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');9 y: n4 ^2 b' Y9 `; H, ]
var transaction = new tx(rawTx);7 |+ v- A5 p& B$ H! _" m
transaction.sign(p);( ^" p' U6 e+ M5 w) v1 O/ K" k0 X
然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
( o% X6 s% `9 R' t' \) d+ z  N( F2 [Etherscan
: X" V* R$ ?4 {5 g4 Q中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
3 P" P1 \7 Y- V! f//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
$ j& |5 n! H# l/ ]接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
- o' B% P+ G! z  D//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
2 R' l1 M# y0 `6 y- a9 D5 S为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));' Q$ p/ ?# x% v8 y; |: f
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
% j; v" Z5 R. @6 Z接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e' e, d+ m( A: |/ ]* c: @
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff
. p' k- ], j. y) L9 ?$ o& m/ d接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);. M& U7 h, ?) d( l* |  _
//0x950041c1599529a9f64cf2be59ffb86072f001114 _2 w: r2 [1 d  w
合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');; P0 I  c" I% `
console.log(contractTx.from);  o! H6 y2 V+ u% f
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
& W; Y+ X8 F  E: Lconsole.log(contractTx.nonce);
* J. [4 o! W  V. m$ S//0/ B6 c9 i! g& j: g9 M
所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));; r7 L8 g* G$ W
//0x950041c1599529a9f64cf2be59ffb86072f00111+ b) U/ n2 ?% r: p# r: K0 K" I
现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站9 u4 a! s0 y2 J- p
https://www.ethereum.org/
  i2 h5 P& f: M; Z" f以太坊的其中一个客户端 Mist 的 GitHub Repo
8 K3 t' |( u+ |1 J. L" ]$ Nhttps://github.com/ethereum/mist/releases. H' p, U. d1 k
Solidity
# x2 f  l8 g' M# t' U. i/ a2 @$ h/ Ihttp://solidity.readthedocs.io/en/latest/3 F3 w4 [0 E$ X% M+ E6 H# q
Web3 api
* {2 L! a9 h' t3 T3 Dhttps://github.com/ethereum/wiki/wiki/JavaScript-API
& c7 k5 E  k$ Y3 r社区讨论& T7 e& N' S3 S; D- w3 }
https://www.reddit.com/r/ethereum/
  |" S1 d& {  s& D+ C如果你有任何关于此文的问题,你可以在我们$ d) b( J* m4 @, t
GitHub nightlyHacks repo
3 b9 ?- r7 v0 ?( I9 o中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14