• 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
  • 相关阅读:
    199. 二叉树的右视图
    二叉树前、中、后、层次、遍历的非递归法
    奇思妙想
    917. 仅仅反转字母【双指针】
    JVM性能监控与故障处理工具
    Java线程池使用和常用参数(待续)
    MySQL常用知识
    手写常用算法
    LightOj 1170
    逆元总结
  • 原文地址:https://www.cnblogs.com/wanghui-garcia/p/10103401.html
Copyright © 2020-2023  润新知