Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
142 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3
' \+ i% `  @$ @% w5 C7 m然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');6 T' R8 f+ Z* q/ s) {
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
. n% E& `+ [& I" F9 I! _var util = require('ethereumjs-util');
* [9 C7 K, k2 @6 L' `var tx = require('ethereumjs-tx');, @. Y% I6 |$ [% m+ }! H: P
首先我们从理解一个私钥开始。以太坊通过+ A% I" w% Q& p7 ]  b
公钥加密
( I0 }( f- U$ Z" X9 K. O! P进行授权。具体来说,用+ q( k, {; o1 ^( m
椭圆曲线数字加密算法" B5 E1 E9 `+ z* B0 `
,通过
) z/ [7 {6 ~3 f7 ]secp256k1: g* t; _7 Y! O$ H
标准生成公钥。除了有一些+ ^) e+ K: E: t' q9 H' t
限制" S! Y  S; T1 |
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';  w' L" Z" @) C/ h9 V- T7 F1 [) H8 ]# v6 B
通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));; o# O: T: b! U( _1 X* a! \( l! f
如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27' G7 M( Z% |7 S. Q) O
与私钥相关联的以太坊地址是用相应公钥进行, @  \0 x7 D$ |
SHA3-256 (Keccak)
  b4 W% W$ f3 `9 d. z哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);) u# B+ g8 o4 n5 b/ U( {, I: O
//0x53ae893e4b22d707943299a8d0c844df0e3d5557
/ ?* y0 J2 p# k* r% D6 ~  Z; \* y正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:* a" V7 }8 s; P* O0 }- n4 P% P" J
nonce:输出交易的次数,从 0 开始+ u9 C9 k8 \' T1 N% y
balance:账户中的以太币数9 X0 H  k# p" z" G4 u$ W
storageRoot:与账户存储相关联的哈希值8 ]/ [2 @6 H& O% [
codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
3 d% R5 ]" s5 _接下来我们看一下交易,交易有 6 个输入域:8 m7 w6 _1 s- k  j3 a; I  _1 Q
nonce:输出交易的次数,从 0 开始
$ I6 }9 @4 W  TgasPrice:交易中花费的单位 Gas 的价格
5 {  O( ~, G9 c$ c4 b; ggasLimit:处理交易允许花费的最大 Gas 量) P2 r: A% e5 c" ]9 H6 e
to:交易发送到的账户,如果是空,交易就会创建合约( ]. M  m: b/ d- v. s5 s+ P
value:发送的以太币的量
& v4 z2 v$ L( e1 f# n% Udata:可以是任意的消息或合约函数调用或创建合约的代码2 ~# A7 G1 |' n5 w1 G$ S! K
一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {% G( E% l. ~6 t, c
    nonce: web3.toHex(0),9 x0 M8 U7 I$ k
    gasPrice: web3.toHex(20000000000),) \( Y* I; K) l2 F- N- T! p. x7 S) [
    gasLimit: web3.toHex(100000)," Y: K  d2 C2 x7 H
    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
! S8 O$ {: I. Y. P6 O8 K5 [# a    value: web3.toHex(1000),+ c' x8 ?& y* [. G2 y% b  n9 U( P
    data: '0xc0de'8 k5 m3 ?7 z. d6 Q/ {0 t
};9 F$ v. d$ @9 f9 ~1 m% g! q0 o% h
注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');3 A! m/ f: T3 `' g" S% l; l0 @" |6 j
var transaction = new tx(rawTx);, D9 n& a7 f8 {$ v% I9 L* M0 c
transaction.sign(p);- _3 e2 e5 v5 S5 p5 x. Q3 j
然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
! b, K. X' O6 c5 U, yEtherscan
" b0 T0 W+ U* B( l  d7 ^: ], J! }' |中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
6 J) P1 g+ G7 K0 T+ [) u//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
" ~5 P- \: W; [( o- G; B0 v5 z接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
- k" o+ [# P! K% J+ t//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff2 h+ l5 z; f  ]. r) |
为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));' k0 a1 w0 e4 [3 K
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b3 h: ?6 b( g; J) y% s
接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e, Y( N3 H  _" p+ X* H/ l0 v; j+ K
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff
: v, T2 T1 I- z3 a( e接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);, l" C; h! O) ?8 Y: T) ]
//0x950041c1599529a9f64cf2be59ffb86072f00111
1 e& w4 E! j1 A; L合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
% s4 C, `* }3 N, Y3 W" w: P* aconsole.log(contractTx.from);; P; J6 r' q; i0 ~
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f  y( ~5 I- v0 [& t5 l) I' D) S
console.log(contractTx.nonce);
+ X- J6 y7 S2 R( H6 _' U//0
7 L0 W5 k0 {5 z1 i1 `! T所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));! e7 D- B+ D9 }
//0x950041c1599529a9f64cf2be59ffb86072f001113 w: i1 {9 ?0 [' n; a
现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站
8 V7 h* G: `- a- fhttps://www.ethereum.org/) R) v4 w. P/ I0 n) e+ s
以太坊的其中一个客户端 Mist 的 GitHub Repo
2 n9 W8 U1 z" N( t# y5 v+ `$ {https://github.com/ethereum/mist/releases
3 V  Z. [  T; A* P( |2 USolidity! H; {9 w, b3 V- T( @* E0 d3 Q
http://solidity.readthedocs.io/en/latest/
" h9 d  `. a/ Z$ q2 AWeb3 api* `) X0 |( v% m9 Q
https://github.com/ethereum/wiki/wiki/JavaScript-API1 O( Z3 J  a/ F
社区讨论
) [& M7 {( s7 Dhttps://www.reddit.com/r/ethereum/
& [- k2 |6 w/ e8 M, U3 i' N; U如果你有任何关于此文的问题,你可以在我们
3 ^& `+ _( Y' j% ?! E6 S$ kGitHub nightlyHacks repo
' {1 l6 o! t/ F6 ~8 ]$ Q% b  O% v中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14