Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
100 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3
& A0 Q1 z& q' N+ F然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');
4 P9 O: L3 ]% n3 q( G$ u; Hvar web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));6 \2 W) Z7 d0 G* ?* {7 _* t1 Y/ O
var util = require('ethereumjs-util');) {. C+ ]6 ^. x& T
var tx = require('ethereumjs-tx');7 Q# P  Z$ I- G
首先我们从理解一个私钥开始。以太坊通过/ q6 d) @: e4 o2 H. A" k
公钥加密; K& @- j6 `4 m
进行授权。具体来说,用: I& ~  h/ y7 {% U
椭圆曲线数字加密算法; `; Y/ @. s+ a. A; j6 y
,通过
4 K' Q* P1 j1 B, b1 s; C7 Esecp256k18 D- u2 ~' q& q5 x5 m
标准生成公钥。除了有一些7 n: ^* G+ z  ]. S
限制  x5 v5 \, ]% s9 S/ s5 V
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';
7 b( ]+ r% P1 b/ F0 v2 o1 E$ @2 I通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));( e) f. ]% g$ R& [1 S- C! M8 M
如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b27
  Z9 @  @* O8 |  f" n, [. P: E与私钥相关联的以太坊地址是用相应公钥进行  @5 E0 e3 j  Z* r/ J: s
SHA3-256 (Keccak)
( @9 I. ~( Q- M1 f6 i: f3 ~哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);  `' T( x" o6 E; I/ v
//0x53ae893e4b22d707943299a8d0c844df0e3d5557
5 d" G6 r* e2 U* B  B正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:
  b5 |) [8 z- ~& ^( G- ~& z8 v7 {! _nonce:输出交易的次数,从 0 开始
3 Y7 S  {; s' c- q' {balance:账户中的以太币数( @6 \& j; |6 ^
storageRoot:与账户存储相关联的哈希值, l' \& w$ F5 `' m
codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
" {& z; y: t* t. E接下来我们看一下交易,交易有 6 个输入域:0 v8 E/ P2 ?5 u* {0 c
nonce:输出交易的次数,从 0 开始
" W) G6 f- t7 y; w  |1 p8 vgasPrice:交易中花费的单位 Gas 的价格
1 l+ Q3 |) V8 s+ _' e, N7 V7 p0 U1 cgasLimit:处理交易允许花费的最大 Gas 量1 E* P/ E# T' u: w
to:交易发送到的账户,如果是空,交易就会创建合约* M& @- V' ~3 q( \8 \3 X
value:发送的以太币的量( T2 v, n3 _7 s& L
data:可以是任意的消息或合约函数调用或创建合约的代码
( _8 _2 H3 y2 I3 X, i0 ^1 W, D一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {# G* X! P" M) a8 \$ W+ A
    nonce: web3.toHex(0),1 f4 @6 Z$ G5 p1 D
    gasPrice: web3.toHex(20000000000),
% D! h! d" R* o2 x' G    gasLimit: web3.toHex(100000),
- `5 Z7 M: a+ t    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
0 {! w8 R! }! S    value: web3.toHex(1000),0 F8 E( R% Q3 |" {
    data: '0xc0de'1 F% T$ x0 Z; t6 D' J' e9 Z
};
* j( G3 {" H1 w0 S& T注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');' [1 V4 O) R3 B
var transaction = new tx(rawTx);9 T9 S7 I9 S, H& v* k. g
transaction.sign(p);
+ R, ]7 i4 C; Y' K. z# i& g( h: Y然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在
: n: S' k- Q* V. l4 i3 OEtherscan9 W4 A4 U( Y# b
中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
# }( X2 N$ B- A' G- \8 c3 Z! V//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
- J8 x% h7 s; G8 R! A接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
% a! e6 \7 p6 V4 c( v3 t* I. _//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
9 `( r3 J) O& V9 M  H9 ?为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));
  i& S: X! }. {7 q; X. m; X6 B, @//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b
+ c1 l% J; T1 h6 A0 g0 X接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e' u1 o5 C, \$ `+ ~( \# _
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff
- G6 m; l# k0 Y! e9 `4 y1 w接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
; g) v$ F4 Y* V# W4 O4 E) g- ]//0x950041c1599529a9f64cf2be59ffb86072f00111
& m* X' ]3 p* A! u5 s  R合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');0 Y/ X4 G/ w% y0 x+ W
console.log(contractTx.from);* t9 g3 U( p) p; X+ K
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f$ O* Z- Q2 }: [- h8 {' P9 u# r
console.log(contractTx.nonce);
) }* B$ h) _5 R( D6 \# f//0& D8 `5 ~$ h) }. ^# P
所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));' X1 `  ^2 w1 s$ K: o
//0x950041c1599529a9f64cf2be59ffb86072f00111
) l+ a: z. \- l5 V' F$ z2 V现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站
0 [0 h3 W. R" Y5 N7 [' rhttps://www.ethereum.org/
. @- D1 k8 {% \1 @以太坊的其中一个客户端 Mist 的 GitHub Repo" W% C9 g7 u8 R0 I8 S, W: {
https://github.com/ethereum/mist/releases
* a  i  _2 `& |: \- B, i$ h, ?Solidity# w% \& O- t, L4 s; N; g% B
http://solidity.readthedocs.io/en/latest/+ m; T) K$ e; n3 e
Web3 api
% U" J' f- r1 x: @: dhttps://github.com/ethereum/wiki/wiki/JavaScript-API
8 |, e$ g2 P) s社区讨论4 X5 g  W- `5 ]. m
https://www.reddit.com/r/ethereum/
0 s% n3 n+ o. O如果你有任何关于此文的问题,你可以在我们
: _( F" h/ W) F6 B  @' WGitHub nightlyHacks repo
1 G" f+ t( E0 y$ G8 e4 l6 d中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14