Contract-Invocation
獲取智能合約的完整狀態
從黃皮書,我發現一個合約有 4 個組成部分 1. nonce, 2. balance, 3. code, 4. storage。要了解智能合約的目前狀態,我們需要了解智能合約的所有這些組件。
如果我使用 geth 客戶端來獲取智能合約的狀態,我可以使用
**eth.getBalance(address)**獲取合約餘額
**eth.getCode(address)**獲取合約程式碼
eth.getTransactionCount(address) for nonce
4.同樣,**eth.getStorageAt(address, index)**獲取特定索引處的儲存。
我既找不到一次下載完整儲存的方法,也找不到直接下載合約完整狀態的方法。
那麼有沒有什麼辦法可以得到一份完整的合約呢?
此處已提出有關完整狀態的問題,但答案不是很有幫助。
無法通過 JSON RPC 或 web3 API 來實現。
我在 Github 上創建了一個儲存庫,其中顯示瞭如何使用 nodejs https://github.com/medvedev1088/ethereum-merkle-patricia-trie-example讀取塊和任何合約儲存中的所有 Patricia trie 條目
var Trie = require('merkle-patricia-tree'); var rlp = require('rlp'); var levelup = require('levelup'); var leveldown = require('leveldown'); var db = levelup(leveldown('/your_home_dir/Library/Ethereum/rinkeby/geth/chaindata')); var keccak256 = require('js-sha3').keccak256; // the block state root, rinkeby, block number 1775804 // the block state root can be obtained by invoking web3.eth.getBlock(<blockNumber>) in `stateRoot` field var root = '0xe4a6ff741ec2e0d0cd274a745756028df27312161bdb4557b6da434349f716a9'; var trie = new Trie(db, root); trie.checkRoot(root, function (err, val) { console.log('Root exists:', val); }); var address = '398A7A69f3c59181A1ffe34bed11DCb5DF863A8a'; var addressHash = keccak256(new Buffer(address, 'hex')); trie.get('0x' + addressHash, function (err, val) { var decodedVal = rlp.decode(val); console.log(decodedVal); if (!decodedVal || decodedVal.length < 4) { console.log('The value for the address must be an array of 4 elements'); return; } // 3rd element in the array is storage root, 1st - nonce, 2nd - balance, 4th - codeHash var storageRoot = decodedVal[2]; console.log('storageRoot', storageRoot); trie.root = storageRoot; trie.checkRoot(storageRoot, function (err, val) { console.log('Storage root exists:', val); }); // Read storage slot with index 0 var slotZeroHash = keccak256(new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')); trie.get('0x' + slotZeroHash, function (err, val) { var decodedVal = rlp.decode(val); console.log('Value at slot 0: ', decodedVal); }); // Read all entries from contract storage var stream = trie.createReadStream(); stream.on('data', function (data) { console.log('key:' + data.key.toString('hex')); // values are rlp encoded var decodedVal = rlp.decode(data.value); console.log(decodedVal); }); stream.on('end', function (val) { console.log('done reading!'); }); });
範例輸出:
Root exists: true Account data: 398A7A69f3c59181A1ffe34bed11DCb5DF863A8a [ <Buffer 01>, <Buffer >, <Buffer 24 21 83 63 90 de b4 32 ce 0e ac fe 5f 49 be 88 99 17 bf 8a fa 07 72 24 1c 30 9e 61 e0 4a 0d 42>, <Buffer 61 60 55 49 c9 7c 3e 7a d6 68 63 3b 72 b2 60 d3 00 5e ab be f3 22 a2 d6 33 2a 49 76 80 89 77 7a> ] Storage root: <Buffer 24 21 83 63 90 de b4 32 ce 0e ac fe 5f 49 be 88 99 17 bf 8a fa 07 72 24 1c 30 9e 61 e0 4a 0d 42> Storage root exists: true Value at slot 0 - key: 290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563 <Buffer 40 9f 9c d8 52 a3 ba e9 52 5d 2a aa> key:0205d9ce8b4a26409d40486b0ac7b8dc356714e840016b19cc5c0f2c8adbcd74 <Buffer 36 35 c9 ad c5 de a0 00 00> key:0249d346d51fad5ef0b6fae89b4907e63c831f4f8af088d602baef47cda4eab7 <Buffer 0a 07 64 07 d3 f7 44 00 00>
有趣的是,這些數據幾乎沒有用,因為你不知道槽索引(你只能看到它們的雜湊值),也不知道值的數據類型。至少您知道合約佔用了多少儲存空間。