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 = '' 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:
returned: 60606040526000357c010000000000000000000000000000000000000000000000000000000090048063454a2ab31461004f578063b9a2de3a14610091578063edd481bb146100d35761004d565b005b6100656004808035906020019091905050610189565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100a760048080359060200190919050506102d2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e960048080359060200190919050506100ff565b6040518082815260200191505060405180910390f35b600060016000818150548092919060010191905055905080508143016000600050600083815260200190815260200160002060005060000160005081905550336000600050600083815260200190815260200160002060005060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b919050565b60006000600060005060008481526020019081526020016000206000509050346012600a8360010160005054011811806101c95750438160000160005054115b1561022d573373ffffffffffffffffffffffffffffffffffffffff16600034604051809050600060405180830381858888f19350505050508060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691506102cc565b8060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008260010160005054604051809050600060405180830381858888f1935050505050338160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055503481600101600050819055503391506102cc565b50919050565b600060006000600050600084815260200190815260200160002060005090508060000160005054431015156103d6578060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1660008260010160005054604051809050600060405180830381858888f19350505050506000816001016000508190555060008160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055506000816000016000508190555060008160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b5b5091905056
address created: 692a70d2e424a56d2c6c27aa97d1a86395877b3a //生成的合约账户地址
----running tx-------
gas used:
returned:
------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: 56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
a6db6bcd1c3757abef01cdf587304df3698a3b1e6b93667fbe87072d261ee7e1 //不为空字符串hash值,说明为合约账户
key: ca35b7d915458ef540ade6068dfe2f44e8fa733c //从key-pair.json得到的账户地址
Value:
//使用其运行了两个交易,所以nonce为2
efd0751d0cf8778001
56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470

ethereumjs-vm/examples/run-transactions-complete的更多相关文章

  1. ethereumjs/browser-builds

    https://github.com/ethereumjs/browser-builds ethereumjs - Browser Builds This repository contains br ...

  2. ethereumjs/ethereumjs-vm-4-tests

    根据代码发现还要了解的模块有: ethereumjs/merkle-patricia-tree -对应数据存储的数据结构 ethereumjs-blockchain —— 区块链 ethereumjs ...

  3. Qt Examples Qt实例汇总

    ActiveQt Examples Using ActiveX from Qt applications. Animation Framework Examples Doing animations ...

  4. Extended VM Disk In VirtualBox or VMware (虚拟机磁盘扩容)

    First, Clean VM all snapshot, and poweroff your VM. vmdk: vmware-vdiskmanager -x 16GB myDisk.vmdk vd ...

  5. PatentTips - Interrupt redirection for virtual partitioning

    BACKGROUND The present disclosure relates to the handling of interrupts in a environment that utiliz ...

  6. Postgresql-xl 调研

    Postgresql-xl 调研 来历 这个项目的背后是一家叫做stormDB的公司.整个代买基于postgres-xc.开源版本应该是stormdb的一个分支. In 2010, NTT's Ope ...

  7. Java Annotations: Explored & Explained--转载

    原文地址:http://www.javacodegeeks.com/2012/08/java-annotations-explored-explained.html One of the many w ...

  8. Understanding User and Kernel Mode

    https://blog.codinghorror.com/understanding-user-and-kernel-mode/ Continue Discussion92 repliesJan ' ...

  9. Java Annotation 机制源码分析与使用

    1 Annotation 1.1 Annotation 概念及作用      1.  概念 An annotation is a form of metadata, that can be added ...

  10. MongoDB - MongoDB CRUD Operations, Query Documents

    Query Method MongoDB provides the db.collection.find() method to read documents from a collection. T ...

随机推荐

  1. 实例-PHP_SELF、 SCRIPT_NAME、 REQUEST_URI区别-获取前台公用文-dirname-PHP的"魔术常量"-str_replace

    Part1:实例 $_SERVER[PHP_SELF], $_SERVER[SCRIPT_NAME], $_SERVER['REQUEST_URI'] 在用法上是非常相似的,他们返回的都是与当前正在使 ...

  2. memcached 细究(三)

    今天研究ecshop的cls_mysql类库, 涉及到mysql 和memcache 的整合 category.php 商品属性帅选时使用memcache缓存 mysql public functio ...

  3. array(1) { [0]=> int(5) }和array(1) { [0]=> string(1) "5" }

    php array数组: $arrayValue = array(5); $arrayValue = array('5'); 的不同之处 一个是整型一个是字符串型 array(1) { [0]=> ...

  4. OpenStack IceHouse 部署 - 3 - 控制节点部署

    Mysql部署配置  安装 安装mysql,mysql的python绑定 apt-get install mysql-server 安装过程中会要求设定mysql的root账户的密码,这里假定设为my ...

  5. 使用iview时,页面没了滚动条

    场景:页面中有一个确认按钮,保存后弹框预览在点保存按钮,实现数据提交.提交后回到数据列表页,用this.$router.push('list'),返回后页面无法滚动了. 原因:排查后发现弹框时在bod ...

  6. Java设计模式—解释器模式&迭代器模式简介

       解释器模式在实际的系统开发中使用得非常少,因为它会引起效率.性能以及维护等问题,一般在大中型的框架型项目能够找到它的身影,如一些数据分析工具.报表设计工具.科学计算工具等,若你确实遇到" ...

  7. LeetCode赛题391----Perfect Rectangle

    #391. Perfect Rectangle Given N axis-aligned rectangles where N > 0, determine if they all togeth ...

  8. How to save rules of the iptables?

    The easy way is to use iptables-persistent. Install iptables-persistent: sudo apt-get install iptabl ...

  9. C++多线程编程(★入门经典实例★)

    原文:http://www.cnblogs.com/codingmengmeng/p/5913068.html 多线程在编程中有相当重要的地位,我们在实际开发时或者找工作面试时总能遇到多线程的问题,对 ...

  10. Rxjava学习(一基础篇)

    一.Rxjava跟EventBus的区别 RxJava 是一个响应式编程框架,通过一种扩展的观察者设计模式来实现异步操作. 跟AsyncTask和Handler类似,但是比AsyncTask和Hand ...