Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

V刘晨曦
102 0 0
以太坊可被看做基于交易的状态机:交易可以改变状态机,状态机可以记录跟踪交易。本文将在一个比较深入的层次考察以太坊交易的组成部分,解释大部分令人费解的十六进制数是怎么确定的。在本教程中,我们使用 node.js,所以我们首先从安装依赖关系开始。$ npm install web3@0.19 ethereumjs-util@4.4 ethereumjs-tx@1.3, T3 P; ]8 p9 E, {( U. f
然后创建文件 tx.js ,请求依赖关系。var Web3 = require('web3');: S- x, L* R& N" q( D3 \7 O& a
var web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/'));
& i5 g! ^) I' g. K2 s6 L7 p6 g. t9 O/ Ivar util = require('ethereumjs-util');9 n2 P+ T" y; k: @3 g
var tx = require('ethereumjs-tx');* Y. O# z3 a1 T
首先我们从理解一个私钥开始。以太坊通过8 z* Z; `) l9 _
公钥加密
% x6 ?/ j) c  R进行授权。具体来说,用+ J1 r  {* E0 |( ]5 Q9 y
椭圆曲线数字加密算法3 y( T( ]+ w, _8 ?
,通过7 D5 G- {& d* [
secp256k1( Y* O9 ]7 p  p4 d
标准生成公钥。除了有一些5 p+ o8 E6 K- p' Q4 p3 o
限制  [0 y8 h8 q2 M0 _4 e7 Z* A* y4 b
外,私钥只是一个随机的 256 位的数。例如:var privateKey = '0xc0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de';
, v/ s0 t" V) }/ M2 h通过私钥导出相应的公钥:var publicKey = util.bufferToHex(util.privateToPublic(privateKey));- q( ]' L0 E3 F$ J; f* r
如果你输出公钥,可以看到下面的 16 进制数:0x4643bb6b393ac20a6175c713175734a72517c63d6f73a3ca90a15356f2e967da03d16431441c61ac69aeabb7937d333829d9da50431ff6af38536aa262497b274 ^6 k! A/ r* i, B, h* w; n9 j
与私钥相关联的以太坊地址是用相应公钥进行
/ O- ?# ]" ~$ l5 {% d3 I' ]8 A% j! C* _SHA3-256 (Keccak)' x0 N5 ~* h* J8 w, b2 q. c
哈希运算后得到的后 160 位。var address = '0x' + util.bufferToHex(util.sha3(publicKey)).slice(26);# {& T* `3 I5 v
//0x53ae893e4b22d707943299a8d0c844df0e3d5557
# S7 J& e; K% ~0 r" Q6 _8 L正如你看到的,多个私钥可以有相同的地址。一个以太坊账户与一个地址相关联,而且每个地址都有以下属性:* N" Q; b1 D+ q9 C/ M1 }8 h0 L
nonce:输出交易的次数,从 0 开始! k  u5 S3 S  \0 Y" U0 k- c
balance:账户中的以太币数
+ i2 ?6 ~, C( K/ d8 Z1 HstorageRoot:与账户存储相关联的哈希值
2 V+ T2 t- Z% ^$ ?! J  _codehash:控制账户的代码的哈希,如果它是空的,那么就是一个正常账户,能够通过私钥访问的,否则,它就是一个智能合约,其交互受到代码的控制
& \  g2 A' j1 [) a! b接下来我们看一下交易,交易有 6 个输入域:* p* f) B' `  U$ ~
nonce:输出交易的次数,从 0 开始/ H* x- |! k2 y, B3 f8 d6 X
gasPrice:交易中花费的单位 Gas 的价格
# r( ^  C8 Y( ?: l6 mgasLimit:处理交易允许花费的最大 Gas 量+ j9 A! C) [6 o: V; k
to:交易发送到的账户,如果是空,交易就会创建合约4 n/ u& t. A, y; `
value:发送的以太币的量
7 k# b: ^' K9 vdata:可以是任意的消息或合约函数调用或创建合约的代码" [0 p! L% K4 r
一个发送 1000wei 以太并且留下消息 0Xc0de 的交易可以被构造如下:var rawTx = {. u4 @" z5 y+ \2 ^7 E
    nonce: web3.toHex(0),7 M( [2 l% q3 c6 ~7 p! o* }, h
    gasPrice: web3.toHex(20000000000),$ `3 O, e  i/ `/ d0 K# C0 S( f6 A
    gasLimit: web3.toHex(100000),$ u$ a8 l2 f) C
    to: '0x687422eEA2cB73B5d3e242bA5456b782919AFc85',
% @  h0 K% l( b. D5 w% b$ `# c! J! x: ~    value: web3.toHex(1000),+ K8 x* r" H( W5 J5 A
    data: '0xc0de'
( u# N2 k7 X9 Q9 T4 D};% l4 Q: r+ ?3 v  c! k
注意, from 地址并没有指定,在私钥签署后,它会从签名中提取。签署交易:var p = new Buffer('c0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0dec0de', 'hex');: ~; y: E; m/ \7 [' Q6 R/ H7 y
var transaction = new tx(rawTx);
/ P9 b6 W/ `2 j6 Ztransaction.sign(p);
% I% x& t/ u7 g4 ?" o- B然后交易就可以发送到网络上,而且能通过一个 256 位的交易 ID 进行追踪。这个交易可以在" }0 |# y6 a6 |& ^* G1 l/ z
Etherscan3 z6 v* X7 U5 z& I; z/ ^
中查看。交易 ID 是交易的哈希值console.log(util.bufferToHex(transaction.hash(true)));
- L& a3 h# v  S) @7 f; x//0x8b69a0ca303305a92d8d028704d65e4942b7ccc9a99917c8c9e940c9d57a9662
, D  K9 k7 H  V* P1 {* r接下来,我们看一下指什么构成了函数调用的数据。以此次合约交易数据为例:console.log(web3.eth.getTransaction('0xaf4a217f6cc6f8c79530203372f3fbec160da83d1abe048625a390ba1705dd57').input);
* ?7 X2 l/ [. Z% B, d+ `//0xa9059cbb0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e000000000000000000000000000000000000000000000000d02ab486cedbffff
4 G# h: }9 V9 D; q% p1 w为了知道调用的是哪个函数,必须提前知道合约的所有的函数,才能创建哈希表。前 32 位 a9059cbb 是函数哈希的前 32 位。在当前情况下,函数为 transfer(address _to, uint256 _value) ,它的哈希为:console.log(web3.sha3('transfer(address,uint256)'));
3 x6 a! q9 Y- c* B* w$ @//0xa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b+ Y6 c' c$ D5 P0 |$ g: `
接下来是参数,每个 256 位,所以当前情况下 address 是:0x0000000000000000000000007adee867ea91533879d083dd47ea81f0eee3a37e( g. A$ K6 L$ W8 l1 K: A
uint256 是:0x000000000000000000000000000000000000000000000000d02ab486cedbffff7 u" c7 V2 b" `/ U* e# y. `/ _! @
接下来,如上所述,通过省略 to 域,可以建立一个合约。但是如何确定合约地址呢?以此交易为例:console.log(web3.eth.getTransactionReceipt('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5').contractAddress);
8 l% U7 v; J0 ]- V//0x950041c1599529a9f64cf2be59ffb86072f001116 I  w& T2 a5 m
合约地址是发送者地址哈希值的后 160 位,而且 nonce 可以提前确定。对于这个交易来说,发送者和 nonce 可以在下列代码中发现:var contractTx = web3.eth.getTransaction('0x77a4f46ff7bf8c084c34293fd654c60e107df42c5bcd2666f75c0b47a9352be5');
; N. N$ n; k1 n$ ?1 m$ Qconsole.log(contractTx.from);6 g: [" p  X  j
//0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f
. N! {7 d" V/ Fconsole.log(contractTx.nonce);
6 Y0 R6 T+ v; l/ p% y//0
# |& m9 |' M$ @+ k; c, `% {1 I/ v所以合约地址是:console.log('0x' + util.bufferToHex(util.rlphash(['0x84f9d8b0e74a7060e20b025c1ea63c2b171bae6f', 0])).slice(26));: o, w  }9 _3 {
//0x950041c1599529a9f64cf2be59ffb86072f00111
% N: P/ j, a# [6 u现在我们算是搞清楚了这些十六进制数的含义!以太坊和智能合约具有打破许多行业的巨大潜力。线上有许多资源,你可以在下面找到几个更多关于以太坊的教程!以太坊主站
  p4 `2 q0 f& ]% N- j% V( e- lhttps://www.ethereum.org/' A% K0 v4 a: p9 W2 K, A; ~
以太坊的其中一个客户端 Mist 的 GitHub Repo
+ E; r. U. h5 s9 B& g" Ohttps://github.com/ethereum/mist/releases  C2 a+ c, x: I$ x; k1 c7 ~# Q2 Q
Solidity
# D- F7 {9 G% `1 a3 i( `+ ^http://solidity.readthedocs.io/en/latest/
% X, L/ V& q% E  f2 r* u: wWeb3 api# s, ~6 m9 G- f; ?
https://github.com/ethereum/wiki/wiki/JavaScript-API
1 E: U+ a) h2 m. ?: x6 U社区讨论
+ V# K# ?) y$ U4 g: w2 W( ahttps://www.reddit.com/r/ethereum/# z0 i8 V& A5 T& Y1 J. O
如果你有任何关于此文的问题,你可以在我们& U$ j2 ~* E& g2 R$ `
GitHub nightlyHacks repo4 x% k7 ^) t: c; K$ v, B( u
中提出。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14