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. 一:Java基础

    /-- 第一章:概念 --/ 1.java特点:跨平台.面向对象.开源 2.JVM是Java虚拟机的缩写,可以实现跨平台 3.java运行原理: 1).编写java源文件,以.java作为后缀名 2) ...

  2. MySQL B+树索引和哈希索引的区别(转 JD二面)

    导读 在MySQL里常用的索引数据结构有B+树索引和哈希索引两种,我们来看下这两种索引数据结构的区别及其不同的应用建议. 二者区别 备注:先说下,在MySQL文档里,实际上是把B+树索引写成了BTRE ...

  3. C# 简单的loading提示控件

    自己画一个转圈圈的控件 using System; using System.Collections.Generic; using System.ComponentModel; using Syste ...

  4. 利用PHP QR Code生成二维码(带logo)

    转自:http://www.cnblogs.com/txw1958/p/phpqrcode.html HP QR Code是一个PHP二维码生成类库,利用它可以轻松生成二维码,官网提供了下载和多个演示 ...

  5. 利用localStorage事件来跨标签页共享sessionStorage

    //干货 利用localStorage事件来跨标签页共享sessionStorage //因为cookie保存字节数量有限,很多童鞋考虑用html5 storage来保存临时数据,Sessionsto ...

  6. html+css 百度首页练习

    这几天看完了<css权威指南>,写了个百度页面,不带js的纯静态,主要目的就是掌握页面布局,字体颜色之类的没有深究. 写完了觉得很简单,毕竟一开始觉得只要模仿的像就行,但是缩小了浏览器窗口 ...

  7. android studio 3.0 以上 查看sharedpreference

    android studio 3.0 以上 查看sharedpreference 点击android studio 右侧的device file explore,找到data / data 目录: 找 ...

  8. 在Oracle/SQL Service中通过Function返回Table

    本函数用途:返回一个Table 在Oracle中实现,范例: --在Types中: create or replace type objTable as object ( s_usercode var ...

  9. NexusFile(文件管理器)

    NexusFile是一款来自于韩国的文件管理器,类似于TotalCommander,拥有两个并排的文件夹窗口. NexusFile软件的特性如下: 基本功能:复制/移动, 复制/剪切/粘贴, 删除/擦 ...

  10. Intel酷睿前世今生(一)

    Intel酷睿系列自诞生起就树立了桌面CPU霸主的地位,酷睿i系列更是无人能敌.它是Intel阻击AMD多核构架的救赎主,也是AMD复兴梦想的收割者.而Intel酷睿系列已经经历几代了,不知还有多少看 ...