Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
138 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3, j- D1 S/ T4 F1 L
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');
2 T8 w8 {. ~, x, G/ L7 o$ b( k: Ovar web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));* y& A8 n: l2 |
var util = require('ethereumjs-util');7 o7 p8 q3 T' G& C! F
var tx = require('ethereumjs-tx');: t7 D4 y) n% p- P1 O% r
首先我们从理解一个私钥开始。以太坊通过! X2 B: F& ]4 e1 d# y
公钥加密4 {: T- X: q, I. o
进行授权。具体来说,用
# Z6 T0 ~& o; E8 @' p/ P. {6 {椭圆曲线数字加密算法2 c7 a* ?$ B9 D3 E
,通过
( U" H3 ]1 t) A" ]( }7 ]secp256k1) a( g1 J/ _/ `* S; R) J) I
标准生成公钥。除了有一些# I6 c- }1 x+ u3 Q( V9 M, m
限制- R% c' a& q2 D% c$ b
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';! |# T* O' i6 W2 |9 ~
通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));
9 F& J3 Y2 _1 s6 G. O! A如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27  L8 S* [/ K9 K: v  W% p
与私钥相关联的以太坊地址是用相应公钥进行& @+ a1 y: r+ i  b7 ?
SHA3-256 (Keccak)
" B8 A# T% ], ~5 C+ b哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
8 a+ e( M8 A" ?# K# L% z! S//0x53ae893e4b22d707943299a8d0c844df0e3d5557: U( {$ P. w* T% ?6 Q+ V3 I
正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:
; @) I0 g$ h1 l: m2 f+ q, Anonce:输出交易的次数,从 0 开始
8 ~' n2 y" m% Zbalance:账户中的以太币数% L" \" k. C+ r8 w
storageRoot:与账户存储相关联的哈希值
! M4 c% d- |, A# I9 mcodehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
. P* H( v. ~0 ]: T# K2 {' t接下来我们看一下交易,交易有 6 个输入域:
; i6 h. I3 p+ M, N/ k& Pnonce:输出交易的次数,从 0 开始
. y6 k; g) S3 F1 a# j- kgasPrice:交易中花费的单位 Gas 的价格7 U9 o- \9 P; U! ]* f# o: ?
gasLimit:处理交易允许花费的最大 Gas 量
0 M/ y/ q! \1 H* Y6 v* U  g( I  d, T6 [to:交易发送到的账户,如果是空,交易就会创建合约: O: I7 F' ?; Q5 k& R  g0 H
value:发送的以太币的量+ P6 h9 a  ~5 i  ^
data:可以是任意的消息或合约函数调用或创建合约的代码
8 v, O+ b. ]5 v; U$ y8 l# u' B一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {
5 O. a- M3 b; `, B& h/ b) K" A# L( b    nonce: web3.toHex(0),
" m; L$ Z& i# P7 ~8 P    gasPrice: web3.toHex(20000000000),- w; Z) u6 ~/ }# k7 I3 Z9 o
    gasLimit: web3.toHex(100000),
; Q8 ~: n: q: \, \2 J! M9 [- Y7 z% n    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
+ [) F/ z. p, N  R  \4 O    value: web3.toHex(1000),
$ i7 ~  i$ e* _$ i    data: '0xc0de'
* L: o2 m4 `; c2 h};
. b0 @) ~9 c8 X注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');, N3 \7 r1 x- B7 S# |
var transaction = new tx(rawTx);3 N; Z0 }0 O" {$ O& k! t  z0 f
transaction.sign(p);/ Z$ J  W. U8 i3 s1 P! Z, a6 T
然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
/ U# r4 b" ^, S' @% x9 B# M- I  mEtherscan% X+ y' i0 h# S
中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));. L' X2 E4 a; ?
//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
( }5 i% e$ X$ G4 S  D6 l接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
  I7 t4 E2 ?! E2 m# g# l//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff- I4 y2 ~. F: S# E/ X4 I
为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));
$ [5 J8 F  p+ o5 U//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
& V  c6 m3 H* [) @接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e3 |( o1 d# w% ~. h. ]' Y
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff  l; Q2 L4 g$ p  Z
接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);7 i4 B% E1 M4 ?" {
//0x950041c1599529a9f64cf2be59ffb86072f00111
' L, g  ?, Q) \- J合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
/ F1 L; r8 B, r5 t* x' a/ jconsole.log(contractTx.from);! A  s$ i$ C9 h% M" K" {
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f' ^, R0 D" q$ a& s1 `. M
console.log(contractTx.nonce);
; i* p% l1 Q) S- [//0- W* R9 R& m: }1 G' [- j3 o
所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));
/ Y! V1 w& ?3 g//0x950041c1599529a9f64cf2be59ffb86072f00111: v, z) p! x' p: o
现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站
0 U' b3 V- }" X: [! Y3 ^$ ihttps://www.ethereum.org/
. O/ }/ p$ i  |( Z$ Q' `以太坊的其中一个客户端 Mist 的 GitHub Repo
0 C4 t( L# i% Thttps://github.com/ethereum/mist/releases
. m1 T0 _& G5 }2 LSolidity
: @. I/ c1 j1 c- r$ q  q  _: ghttp://solidity.readthedocs.io/en/latest/& P: j8 x$ a8 N
Web3 api
& @: m6 h% Q' z: @4 ~* h3 c: phttps://github.com/ethereum/wiki/wiki/JavaScript-API
, _# i" D8 R" r1 }5 f$ ~社区讨论7 P9 F' ?: S+ O! v
https://www.reddit.com/r/ethereum/
! m0 r3 F9 r% I) _如果你有任何关于此文的问题,你可以在我们
" B3 M8 w- }6 ~8 L; [GitHub nightlyHacks repo
+ F& b9 ?$ d5 a- b中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14