Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
146 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3
' L  e/ \; z& |然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');
3 d7 r* o+ k& `; Hvar web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));0 |* \* E, B: J1 U- j
var util = require('ethereumjs-util');
4 \9 m7 N0 O6 T& {$ Bvar tx = require('ethereumjs-tx');2 A5 c/ m7 ]* v
首先我们从理解一个私钥开始。以太坊通过- W) y% j4 I# U! o& V0 V/ z3 R
公钥加密/ x; c/ D: E9 q6 c3 M
进行授权。具体来说,用; L5 c/ |' |, f$ o
椭圆曲线数字加密算法9 l2 Y) Y; T' y5 d/ H6 Q
,通过' G! K& [. O" s8 E' `! r. p2 p
secp256k1
3 M) u7 }0 |# T. ]) @' D标准生成公钥。除了有一些
1 Z2 q+ K, g9 J+ l限制
$ t$ Y- U- X+ B/ I. \: L7 S外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';
: R6 B# Y$ g/ ]/ u* ^7 S通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));7 a% f- T* r5 {: A- Y" S. g: R
如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27  ]- W. M  _) c8 {- C
与私钥相关联的以太坊地址是用相应公钥进行- [4 h) J) o1 c, G" Z" N) r: z) g0 b2 k
SHA3-256 (Keccak)4 R# Z2 J  D9 n
哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);/ }0 N. m$ m  x, u7 ^0 K! P$ @
//0x53ae893e4b22d707943299a8d0c844df0e3d5557) Y! ]6 n- f3 D
正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:3 x& u2 a# P5 b  \; e, N! f
nonce:输出交易的次数,从 0 开始0 L0 _+ ?/ j4 x& T) ~
balance:账户中的以太币数
/ ]" l: G6 a- o0 Z( _- G+ FstorageRoot:与账户存储相关联的哈希值
5 z) v0 S+ ?$ g' w" R+ O% u! ~codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
  U# f# `: I5 ]0 B接下来我们看一下交易,交易有 6 个输入域:
( e1 {7 H6 \* }. r+ @* mnonce:输出交易的次数,从 0 开始2 j$ W6 S+ C) H* ]; F# n
gasPrice:交易中花费的单位 Gas 的价格
) l* J( E  i1 n. G5 lgasLimit:处理交易允许花费的最大 Gas 量) W0 U$ u4 u6 y0 u0 ^# \$ O: \
to:交易发送到的账户,如果是空,交易就会创建合约! P9 E1 o$ B8 X
value:发送的以太币的量
) r% F/ ^3 B3 U: W  C  ~( kdata:可以是任意的消息或合约函数调用或创建合约的代码
& ^3 k0 |' g! V1 w5 l一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {" t$ M# m" V3 K% U
    nonce: web3.toHex(0),
5 _% W/ |1 T5 g$ K3 J+ d    gasPrice: web3.toHex(20000000000),; C3 x& H. Q8 t' ~  |6 ?- [" J4 ?
    gasLimit: web3.toHex(100000),
* n) h" K4 W: Z- n    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',9 c; R# b# o7 g  v1 e3 W* E
    value: web3.toHex(1000),
  Z% l) M- Q. f- o) {1 |( L* t% O& R7 @/ L    data: '0xc0de'
9 V- K0 P2 ]+ r$ G$ S2 j3 F+ E# o. f};
# \8 W( b0 }2 f注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');( ]6 X4 o/ E* x: n. ~3 z
var transaction = new tx(rawTx);
- @5 X0 R5 w& Z! A* ]) r9 ctransaction.sign(p);4 k) Q- @# D4 B
然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
0 P" N0 p" R; e0 y& E7 NEtherscan
. t# o) F5 U  O+ i% I中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));5 K, \9 G. t0 r
//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
4 D+ z1 V: T' U* a接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
( H) @$ @+ y. O6 D//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
5 \; Z. P2 Y3 u为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));
& h" Q1 M& {1 w' d//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b. e4 f0 K7 {0 _: M& P9 H6 ]
接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e6 O7 O- \: F- ~% c
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff
' N6 X0 {& Q8 M- _. n接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);7 d& C( {$ i3 P
//0x950041c1599529a9f64cf2be59ffb86072f00111
9 S  C9 j6 Y2 g% f( F5 G合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');5 g  ~5 r* r- A' J
console.log(contractTx.from);
' _# z# Y, N2 w9 S  |( z- U//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f. n6 [- C& [" g( t. Y* n4 G+ J' {
console.log(contractTx.nonce);! K+ G# M/ C/ k& Q" o! s
//0/ E* Y; S: ?7 ~* C" d) N: q& K
所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));
3 `" J! {# \/ k6 a, E//0x950041c1599529a9f64cf2be59ffb86072f001112 e3 ?) _' Y  u$ q7 T1 k5 y" b* m
现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站0 h6 l- S/ ^  C( M
https://www.ethereum.org/
: j6 f2 ~( I+ _! F# n5 j2 H. j以太坊的其中一个客户端 Mist 的 GitHub Repo5 @2 d* R* F5 r+ w/ _# s+ M3 r
https://github.com/ethereum/mist/releases
: k/ _, M) D) W+ {! ISolidity
0 O$ h7 c$ o5 I( T% d! ahttp://solidity.readthedocs.io/en/latest/3 Z: P+ G5 S# K/ Z, D0 c
Web3 api& K9 i( j! V4 x
https://github.com/ethereum/wiki/wiki/JavaScript-API' e3 i+ y' P4 c% z  k0 [
社区讨论0 S3 D4 d" m5 s% [3 {- T( t2 z
https://www.reddit.com/r/ethereum/  C: H- \& G  X3 S8 O7 T
如果你有任何关于此文的问题,你可以在我们6 m8 ~8 r: l+ H% g
GitHub nightlyHacks repo
& {& ^7 e6 w, \! N中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14