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. [javaSE] GUI(Action事件)

    对自己定义的类规范化一下,事件和图形化组件分离出来 定义一个类FrameDemo 定义成员属性Frame frame 定义成员属性Botton 定义构造方法FrameDemo() 定义初始化方法ini ...

  2. Java学习--jsp基础语法

    <%!   %>和<%  %>的区别: <%! //1.可定义方法 //2.可定义static方法 //3.可定义static属性 //4.不可以使用out对象 %> ...

  3. golang json 处理的一些例子代码

    json 处理的例子代码, 解析结果看后面注释.   package main import "encoding/json" import "fmt" impo ...

  4. php中::是什么意思?

    类中静态方法和静态属性的引用方法(两个冒号(::)是对类中的方法的静态引用:也就是不需要实例化对象,直接通过类名对类中的方法进行引用)例如: class Test{ public static $te ...

  5. grunt-contrib-watch 监控 JS 文件改变来运行预定义的Tasks

    依赖于 GruntJs ~0.4.0 监控 JS 文件改变来运行预定义的Tasks Demo: watch: { scripts: { files: ['src/**/*.js'], tasks: [ ...

  6. 线性规划费用流解法(Bzoj1061: [Noi2008]志愿者招募)

    题面 传送门 Sol 线性规划费用流解法用与求解未知数为非负数的问题 这道题可以列出一堆形如 \(x[i]+x[j]+x[k]+...>=a[p]\) 的不等式 我们强行给每个式子减去一个东西, ...

  7. WinForm实现Rabbitmq官网6个案例-Topics

    代码: namespace RabbitMQDemo { public partial class Topics : Form { private string exchangeName = &quo ...

  8. Word 最后一页无法删除-解决办法

    Word 最后一页无法删除-解决办法 制服 word 最后一页无法删除 今天在做一个简历的时候,编辑 word 文档的时候,最后一页空白页怎么也删不掉,百度了很多方法之后,只有一个可行,记录一下. 1 ...

  9. JS 日期与时间戳相互转化

    1.日期格式转时间戳 function getTimestamp(time) { return Date.parse(new Date(time)); } 2.时间戳转日期格式 function tr ...

  10. bootstrap-table 分页增删改查之一(增加 删除)

    先上效果图 引入js文件 <!--js jquery --> <script type="text/javascript" src="${pageCon ...