科普 | 以太坊改进建议(EIP)演示
作为一个开源项目,以太坊在 Github 上通过以太坊改进建议(Ethereum Improvement Proposal,简称EIP)系统寻找并讨论有关协议的新点子。这里我们来看一下 EIP#155,一个简单的重放攻击(replay attack)保护。在 EIP#155 之前, 每个以太坊交易有6个输入,也就是
nonce
gasPrice
gasLimit
to
value
data
在之前有关转账的文章中,我们收到了很多有关什么是交易对象以及具体要把什么值进行哈希函数(hashed)运算的问题。为了回答这些问题,首先把6个输入值不记名地按顺序放在一个数组中,然后运用递归长度前缀(Recursive Length Prefix,简称 RLP)编码获得交易的便携式表示,再用 Keccak-256 对其哈希运算。这里有更多关于 RLP 的解释与操作。本文我们也会直接使用 RLP 与哈希函数(hash functions)来更好地描述这点,而不是使用便捷函数(convenient functions)。
很容易观察到,某交易不是在特定一条链上,也就是说,如果你在一个私人的以太坊网络,那么其他人可以在这个网络捕获你的交易并将其广播到公共网络,令交易生效。因此,如果你在不同网络使用相同的地址,可能会导致交易意外地发送。一个简易的修复方法是在 Morden 公共测试网上将所有交易都以一个很大的随机数(nonce)开头,而不是像 EIP#155 那样通过把链 ID 涵盖在交易中这种更常用的方法来修复,主要的公共网络的链 ID 是 1,而新的Ropsten公共测试网络的链 ID 是 3,因此在你自己的网络中应该使用其他数字。
然而,对向后兼容(backward compatibility)来说旧的交易依然有效。
这里我们将展示一个 EIP 上给的例子。我们用的是 nodejs,所以我们首先创建一个文件 tx.js
,并请求函数相关关系。
var Web3 = require('web3');
var web3 = new Web3();
var util = require('ethereumjs-util');
给出的例子是
var transaction = [
web3.toHex(9),
web3.toHex(20000000000),
web3.toHex(21000),
'0x3535353535353535353535353535353535353535',
web3.toHex('1000000000000000000'),
'',
web3.toHex(1),
0x0,
0x0
];
与旧交易进行比较
var transactionOld = [
web3.toHex(9),
web3.toHex(20000000000),
web3.toHex(21000),
'0x3535353535353535353535353535353535353535',
web3.toHex('1000000000000000000'),
''
];
接下来我们用 RLP 编码,经过哈希运算,并输出结果。
var encoded = util.rlp.encode(transaction);
console.log(util.bufferToHex(encoded));
//0xec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080
var encodedHash = util.sha3(encoded);
console.log(util.bufferToHex(encodedHash));
//0xdaf5a779ae972f972197303d7b574746c7ef83eadac0f2791ad23db92e4c8e53
然后我们签名并在每个 EIP 的签名中添加 v 值。
var p = new Buffer('4646464646464646464646464646464646464646464646464646464646464646', 'hex');
var sig = util.ecsign(encodedHash, p);
sig.v += 1 * 2 + 8;
console.log(util.bufferToHex(sig.v));
console.log(util.bufferToHex(sig.r));
console.log(util.bufferToHex(sig.s));
//0x25
//0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276
//0x67cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83
因此已签名的交易变成
var signedTransaction = util.rlp.encode([
web3.toHex(9),
web3.toHex(20000000000),
web3.toHex(21000),
'0x3535353535353535353535353535353535353535',
web3.toHex('1000000000000000000'),
'',
sig.v,
sig.r,
sig.s
]);
console.log(util.bufferToHex(signedTransaction));
//0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83
我们已经浏览了这个 EIP 的变化过程。就像之前提到的,旧库创建的交易依然有效,所以现存的网络中到底还有多少这样的交易?有个简单的方法可以知道答案,因为由旧库创建的交易还保留有 0x1b 与 0x1c 的 sig.v 值,而新库创建的交易只有 0x25 与 0x26 的值。创建一个新文件 find.js,然后运行以下代码看看
var Web3 = require('web3');
var web3 = new Web3(new Web3.providers.HttpProvider('https://mainnet.infura.io/'));
console.log(web3.eth.getTransaction('0x4b420c328f11bbf4cc0043af7bd8b170026e97ef4261e93354bf080c2d04ea6d').v);
//0x26
console.log(web3.eth.getTransaction('0x79fbfd4daa09f7947595f6c1e3d8e78b4032cf64d105292b10f61ebb067d2bcf').v);
//0x1b
用这种方法,我们从第 3,153,001 个区块至第 3,159,000 个区块中搜索每一个交易,一共 6000 个区块,也就是大约 1 天所得到的区块。得到结果为
blocks: 6,000
transactions: 53,114
0x1b, 0x1c: 6,856 (12.9%)
0x25, 0x26: 46,258 (87.1%)
可见仍然有大量旧交易存在,所以请更新你的客户端或库,避免交易重复。
现在我们已经对 EIP#155 有了更多的了解了。
以太坊与智能合约具有影响很多行业的巨大潜力。 要想继续以太坊探索之旅,网上有非常多资源,读者也可以浏览以下的一些链接。
以太坊主页: https://www.ethereum.org/
Mist(以太坊客户端之一) :https://github.com/ethereum/mist/releases
Solidity:http://solidity.readthedocs.io/en/latest/
Web3 api:https://github.com/ethereum/wiki/wiki/JavaScript-API
社区讨论:https://www.reddit.com/r/ethereum/
如果您对本文有任何疑问,可以在 Github 的 nightlyHacks repo 中提出来。
更多更新请关注我们的 Twitter 与 Medium 。
想了解更多我们的工作,请阅读我们的白皮书。
原文链接: https://medium.com/@codetractio/walkthrough-of-an-ethereum-improvement-proposal-eip-6fda3966d171
作者: CodeTract
翻译&校对: 杨哲 & Elisa
杨哲
在探索中增值
你可能还会喜欢:
科普 | ERC 和 EIP 代表什么呢?<https://ethfans.org/posts/what-do-erc-and-eip-stand-for>
ERC721: Non-fungible Token Standard
干货 | 【虚拟货币钱包】从 BIP32、BIP39、BIP44 到 Ethereum HD Wallet