ethereumjs-vm/examples/run-transactions-complete

1.设置账户:

ethereumjs-vm/examples/run-transactions-complete/key-pair.json

{
  "secretKey": "3cd7232cd6f3fc66a57a6bedc1a8ed6c228fff0a327e169c2bcc5e869ed49511",
  "publicKey": "0406cc661590d48ee972944b35ad13ff03c7876eae3fd191e8a2f77311b0a3c6613407b5005e63d7d8d76b89d5f900cde691497688bb281e07a5052ff61edebdc0"
}

 

2.设置的要运行的交易:

ethereumjs-vm/examples/run-transactions-complete/raw-tx1.json

{
  "nonce": "0x00",
  "gasPrice": "0x09184e72a000",
  "gasLimit": "0x90710",
  "data": "0x60606040526103dd806100126000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063454a2ab31461004f578063b9a2de3a14610091578063edd481bb146100d35761004d565b005b6100656004808035906020019091905050610189565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100a760048080359060200190919050506102d2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e960048080359060200190919050506100ff565b6040518082815260200191505060405180910390f35b600060016000818150548092919060010191905055905080508143016000600050600083815260200190815260200160002060005060000160005081905550336000600050600083815260200190815260200160002060005060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b919050565b60006000600060005060008481526020019081526020016000206000509050346012600a8360010160005054011811806101c95750438160000160005054115b1561022d573373ffffffffffffffffffffffffffffffffffffffff16600034604051809050600060405180830381858888f19350505050508060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691506102cc565b8060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008260010160005054604051809050600060405180830381858888f1935050505050338160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055503481600101600050819055503391506102cc565b50919050565b600060006000600050600084815260200190815260200160002060005090508060000160005054431015156103d6578060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008260010160005054604051809050600060405180830381858888f19350505050506000816001016000508190555060008160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055506000816000016000508190555060008160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b5b5091905056"
}

上面这个交易是设置了一个合约

 

ethereumjs-vm/examples/run-transactions-complete/raw-tx2.js

var bidSig = '0x454a2ab3'
var time = '0000000000000000000000000000000000000000000000000000000000000045'

var rawTx2 = {
  nonce: '0x01',
  gasPrice: '0x09184e72a000',
  gasLimit: '0x20710',
  value: '0x10',
  to: '0x692a70d2e424a56d2c6c27aa97d1a86395877b3a',
  data: bidSig + time
}

module.exports = rawTx2

这个交易则是调用了合约中的某个函数

 

3.运行

ethereumjs-vm/examples/run-transactions-complete/index.js

/*
 * Example - Run code contain within transactions
 *
 *
 * Execute it with `node index.js`
 */

var Buffer = require('safe-buffer').Buffer // use for Node.js <4.5.0
var async = require('async')
var VM = require('./../../index.js')
var Account = require('ethereumjs-account')
var Transaction = require('ethereumjs-tx')
var Trie = require('merkle-patricia-tree')
var rlp = require('rlp')
var utils = require('ethereumjs-util')

// creating a trie that just resides in memory
var stateTrie = new Trie()

// create a new VM instance
var vm = new VM({state: stateTrie}) //stateTrie就是区块上的state merkle-patricia树,用于存储区块上的所有账户的信息

// import the key pair
//   pre-generated (saves time)
//   used to sign transactions and generate addresses
var keyPair = require('./key-pair')

var createdAddress

// Transaction to initalize the name register, in this case
// it will register the sending address as 'null_radix'
// Notes:
//   - In a transaction, all strings as interpeted as hex
//   - A transaction has the fiels:
//     - nonce
//     - gasPrice
//     - gasLimit
//     - data
var rawTx1 = require('./raw-tx1')

// 2nd Transaction
var rawTx2 = require('./raw-tx2')

// sets up the initial state and runs the callback when complete
// 设置初始状态,在完成时运行回调函数
function setup (cb) {
  // the address we are sending from
  var publicKeyBuf = Buffer.from(keyPair.publicKey, 'hex')
  var address = utils.pubToAddress(publicKeyBuf, true)
  console.log(address.toString('hex'));//账户address为ca35b7d915458ef540ade6068dfe2f44e8fa733c
  // create a new account
  var account = new Account()//创建一个空账户
  // give the account some wei.
  //    Note: this needs to be a `Buffer` or a string. All
  //      strings need to be in hex.
  account.balance = '0xf00000000000000001' //设置账户balance余额的值

  // store in the trie,将该账户存储到前缀树中
  stateTrie.put(address, account.serialize(), cb) //将该address与账户状态的信息相关联并存储在了区块链上的state前缀树上,区块头上的stateRoot就是该state前缀树的root值
}

// runs a transaction through the vm
function runTx (raw, cb) {
  // create a new transaction out of the json
  var tx = new Transaction(raw)

  // tx.from,对该交易进行签名
  tx.sign(Buffer.from(keyPair.secretKey, 'hex'))

  console.log('----running tx-------')
  // run the tx \o/
  vm.runTx({//运行交易
    tx: tx
  }, function (err, results) {
    createdAddress = results.createdAddress //返回运行该交易生成的合约地址信息
    // log some results
    console.log('gas used: ' + results.gasUsed.toString()) //得到使用的gas值
    console.log('returned: ' + results.vm.return.toString('hex'))
    if (createdAddress) {
      console.log('address created: ' +
          createdAddress.toString('hex'))
    }

    cb(err)
  })
}

var storageRoot // used later

// Now lets look at what we created. The transaction
// should have created a new account for the contract
// in the trie.Lets test to see if it did.
// 交易应该为在前缀树上的合约创建了一个账户,即合约账户。下面查看是否如此
function checkResults (cb) {
  // fetch the new account from the trie.
  stateTrie.get(createdAddress, function (err, val) {//val为该合约帐号的RLP序列化的值account.serialize()
    var account = new Account(val)//所以可以用它来初始化一个账户,然后得到下面的信息

    storageRoot = account.stateRoot // used later! :)
    console.log('------results------')
    console.log('nonce: ' + account.nonce.toString('hex'))
    console.log('balance in wei: ' + account.balance.toString('hex'))
    console.log('stateRoot: ' + storageRoot.toString('hex'))
    console.log('codeHash:' + account.codeHash.toString('hex'))
    console.log('-------------------')
    cb(err)
  })
}

// So if everything went right we should have "null_radix"
// stored at "0x9bdf9e2cc4dfa83de3c35da792cdf9b9e9fcfabd". To
// see this we need to print out the name register's
// storage trie.
//如果上面的部分都成功运行的话,那么应该会有value = "null_radix"存储在key = "0x9bdf9e2cc4dfa83de3c35da792cdf9b9e9fcfabd"中
//要看到这一点,我们需要打印出名字寄存器的存储前缀树
function checkResults2 (cb) {
  // fetch the new account from the trie.
  stateTrie.get('0x9bdf9e2cc4dfa83de3c35da792cdf9b9e9fcfabd', function (err, val) {//并没有得到上面所说的value = "null_radix" ???
    console.log('------results2------')
    console.log(val);
    console.log('------------')
    cb(err)
  })
}


// reads and prints the storage of a contract
// 读取并打印合约的存储
function readStorage (cb) {
  // we need to create a copy of the state root
  var storageTrie = stateTrie.copy() 
  console.log(storageRoot.toString('hex'));//56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421,即null的RLP编码的Keccak-256 hash值
  console.log(storageTrie.root.toString('hex'));//a7d73ff53f4b8722d594cb0462907879e58d95e5784c05510ce5419c52331be5
  // Since we are using a copy we won't change the
  // root of `stateTrie`
  // 由于我们使用的是副本,所以不会更改stateTrie的根.但是运行的结果发现是改了的
  // 将下面的注释掉,才能够通过stream.on('data'...得到前缀树中的信息
  // storageTrie.root = storageRoot //将刚刚上面生成的合约账户的stateRoot赋值到storageTrie.root
  console.log(storageTrie.root.toString('hex'));//storageTrie.root = storageRoot后storageTrie.root变为56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421,即null的RLP编码的Keccak-256 hash值,这样下面的stream.on('data'...是得不到返回值的
  var stream = storageTrie.createReadStream() //创建可读流

  console.log('------Storage------')

  // prints all of the keys and values in the storage trie
  // 打印所有在存储前缀树中的keys和values
  stream.on('data', function (data) {
    // remove the 'hex' if you want to see the ascii values
    console.log('key: ' + data.key.toString('hex'))
    // console.log('Value: ' + rlp.decode(data.value).toString())
    console.log('Value: ');
    rlp.decode(data.value).map(item => {//数组内的值分别是nonce,balance,stateRoot,codehash
      console.log(item.toString('hex'));
    })
  })

  stream.on('end', cb)
}

// run everything
async.series([//按下面的顺序进行运行
  setup,
  async.apply(runTx, rawTx1),//运行了两个交易
  async.apply(runTx, rawTx2),
  checkResults,
  checkResults2,
  readStorage
])

// Now when you run you should see a complete trace.
// `onStep` provides an object that contains all the
// information on the current state of the `VM`.

返回:

userdeMBP:run-transactions-complete user$ node index.js
ca35b7d915458ef540ade6068dfe2f44e8fa733c //从key-pair.json得到的账户地址
----running tx-------
gas used: 312834
returned: 60606040526000357c010000000000000000000000000000000000000000000000000000000090048063454a2ab31461004f578063b9a2de3a14610091578063edd481bb146100d35761004d565b005b6100656004808035906020019091905050610189565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100a760048080359060200190919050506102d2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e960048080359060200190919050506100ff565b6040518082815260200191505060405180910390f35b600060016000818150548092919060010191905055905080508143016000600050600083815260200190815260200160002060005060000160005081905550336000600050600083815260200190815260200160002060005060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b919050565b60006000600060005060008481526020019081526020016000206000509050346012600a8360010160005054011811806101c95750438160000160005054115b1561022d573373ffffffffffffffffffffffffffffffffffffffff16600034604051809050600060405180830381858888f19350505050508060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691506102cc565b8060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008260010160005054604051809050600060405180830381858888f1935050505050338160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055503481600101600050819055503391506102cc565b50919050565b600060006000600050600084815260200190815260200160002060005090508060000160005054431015156103d6578060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008260010160005054604051809050600060405180830381858888f19350505050506000816001016000508190555060008160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055506000816000016000508190555060008160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b5b5091905056
address created: 692a70d2e424a56d2c6c27aa97d1a86395877b3a //生成的合约账户地址
----running tx-------
gas used: 29746
returned: 0000000000000000000000000000000000000000000000000000000000000000
------results------
nonce: 
balance in wei: 
stateRoot: 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421 //null的RLP编码的Keccak-256 hash值
codeHash:c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 //即空字符串hash值,说明为外部账户
-------------------
------results2------
null
------------
56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
a7d73ff53f4b8722d594cb0462907879e58d95e5784c05510ce5419c52331be5
a7d73ff53f4b8722d594cb0462907879e58d95e5784c05510ce5419c52331be5
------Storage------
key: 0000000000000000000000000000000000000000 //空账户,默认存在;有时省略账户时则使用它
Value: 

2f8ae2f307888000
56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
key: 692a70d2e424a56d2c6c27aa97d1a86395877b3a
Value: 
01

56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
a6db6bcd1c3757abef01cdf587304df3698a3b1e6b93667fbe87072d261ee7e1   //不为空字符串hash值,说明为合约账户
key: ca35b7d915458ef540ade6068dfe2f44e8fa733c //从key-pair.json得到的账户地址
Value: 
02  //使用其运行了两个交易,所以nonce为2
efd0751d0cf8778001
56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

 

posted @ 2018-12-12 12:09  慢行厚积  阅读(261)  评论(0编辑  收藏  举报