Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
101 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.39 W0 G5 X) t; \$ i$ X% D
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');* q, y1 Y6 u8 L9 v# X
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
9 ~& P0 }% x/ h% v+ v: wvar util = require('ethereumjs-util');+ f: o  R( H% `% {8 A) r
var tx = require('ethereumjs-tx');
9 A1 O, H5 H0 c. C" J# O首先我们从理解一个私钥开始。以太坊通过
  q! X- k2 k( I8 ^' {1 [公钥加密
6 L5 t+ u- A% _5 _进行授权。具体来说,用
$ o. ]# U6 K- s) N/ ?: H5 v# t椭圆曲线数字加密算法, _& b: O) c2 D" N6 H
,通过- l- s" Z3 o% {. m! j5 P# ?1 C
secp256k1. e8 c# ]2 L) A% h) t/ G4 I' E
标准生成公钥。除了有一些. f7 ^' N! m8 M0 h/ N9 Z
限制) }- G4 z0 [6 z4 S
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';  M9 r3 N4 e0 [9 P8 d+ ]  a
通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));/ L# r% k3 a4 j7 x
如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27
4 r) N+ f* n$ k与私钥相关联的以太坊地址是用相应公钥进行8 m" f# R: y' k; O4 \5 M. C, P
SHA3-256 (Keccak)# }- x0 K: ?* z! O1 Y% c' P
哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);
# p9 F7 g- B! I& C+ Y! d//0x53ae893e4b22d707943299a8d0c844df0e3d5557
1 A/ Q8 [! C' @7 H8 D正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:: f) \; G6 s' M
nonce:输出交易的次数,从 0 开始
8 K; x& h+ l1 T- Abalance:账户中的以太币数
" S$ n% V% _$ P! ^9 \! fstorageRoot:与账户存储相关联的哈希值
7 l' ]/ t  ?' H9 a9 l" @. xcodehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制5 u  X8 n+ T5 W
接下来我们看一下交易,交易有 6 个输入域:' ~0 p, C8 P, n9 t
nonce:输出交易的次数,从 0 开始3 I% o! D0 M$ r: E$ Y5 R- A
gasPrice:交易中花费的单位 Gas 的价格# `- y/ d0 [8 w8 k. m4 ?
gasLimit:处理交易允许花费的最大 Gas 量" k: b' O# L3 u5 a+ }
to:交易发送到的账户,如果是空,交易就会创建合约
( K; ~/ |* ~- |7 M. |6 U3 F  Qvalue:发送的以太币的量
# b& t+ u" S- ~2 s/ ?" jdata:可以是任意的消息或合约函数调用或创建合约的代码$ U" P5 X/ P" j$ ?, h! k) q0 W. p
一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {0 L5 M, j; n# }  M. i
    nonce: web3.toHex(0),
' V2 A: X! ?5 z. X    gasPrice: web3.toHex(20000000000),! M  m9 {8 X9 o+ j4 q, c
    gasLimit: web3.toHex(100000),
% Q0 Q" n9 a" s  d+ D0 S    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',0 m8 Z0 B" {# Y7 f6 w: J
    value: web3.toHex(1000),
- K9 Q& }" p, T! t! y- }+ Q) D    data: '0xc0de'& p& d6 E+ t1 g
};+ H* O+ A- R+ f' k
注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');
( M1 U8 _; R7 rvar transaction = new tx(rawTx);
' f8 r+ ?! q! Xtransaction.sign(p);
- q+ A1 C) ^: B5 J1 G然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在9 u, |  ?/ @+ \
Etherscan9 Q# W# v8 _" A) Z* P4 A: i
中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));0 Q1 ?0 ^0 D) G. o! k/ w# S
//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a96621 A4 X) n0 q8 o+ w5 g0 g. S! k
接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);1 F8 j! V4 }0 }% o& r% C6 C8 }
//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
% q7 z+ X/ \3 v为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));9 @( O8 e4 V# j( C5 L: q: L
//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b7 {( I, ^( d# G+ l) ]
接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e
, h% x- T0 _: Z, u3 t! I# Guint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff. |$ y  L# w% n3 C/ X1 m0 }
接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);. z# w% e) \8 [4 W
//0x950041c1599529a9f64cf2be59ffb86072f00111
8 ?3 ^6 L0 s$ }" E. F2 V( ?2 N* P合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
4 e$ T2 W6 ~4 p# O2 [8 ?' B) Qconsole.log(contractTx.from);
! I8 j6 T4 R% @. z2 \, ?4 \//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
, H8 t. Y6 X- l: Q7 m/ Fconsole.log(contractTx.nonce);, ^3 X; k7 Z, [" {8 J
//08 x- ^. v6 L* O' ?9 j; e% ?
所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));
8 z, F( D4 y& ~8 a; Q//0x950041c1599529a9f64cf2be59ffb86072f00111
: b5 @  V& m7 _( m) n# t# G现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站
, V, N, f: E0 d! K0 u  m# h+ bhttps://www.ethereum.org/, q4 t6 K4 U! ^5 V) t6 g' h
以太坊的其中一个客户端 Mist 的 GitHub Repo
8 I; U% a+ \4 _, \! ?* Jhttps://github.com/ethereum/mist/releases0 d% ]; U9 w/ Y  ?, Y
Solidity: \" w+ F3 B1 F2 A9 F
http://solidity.readthedocs.io/en/latest/
5 }3 ]4 U$ d( w5 h; ?Web3 api
1 Z, y8 Y; M, C. V1 a9 U+ A% hhttps://github.com/ethereum/wiki/wiki/JavaScript-API7 }3 U2 ?8 n9 O3 b( {
社区讨论
5 h, d+ D' G- B- vhttps://www.reddit.com/r/ethereum/) F# T. o: K7 H5 C
如果你有任何关于此文的问题,你可以在我们
7 x: d1 ^4 ]' g' s6 `GitHub nightlyHacks repo
0 O6 C5 z. u; d) ^" T9 {中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14