vaporyjs-vm
Version:
an vapory VM implementation
206 lines (168 loc) • 9.8 kB
Markdown
# SYNOPSIS
[](https://www.npmjs.org/package/vaporyjs-vm)
[](https://travis-ci.org/vaporyjs/vaporyjs-vm)
[](https://gitter.im/vapory/vaporyjs-lib) or #vaporyjs on freenode
[](https://github.com/feross/standard)
Implements Vapory's VM in JS
# INSTALL
`npm install vaporyjs-vm`
# USAGE
```javascript
var VM = require('vaporyjs-vm')
//create a new VM instance
var vm = new VM()
var code = '7f4e616d65526567000000000000000000000000000000000000000000000000003055307f4e616d6552656700000000000000000000000000000000000000000000000000557f436f6e666967000000000000000000000000000000000000000000000000000073661005d2720d855f1d9976f88bb10c1a3398c77f5573661005d2720d855f1d9976f88bb10c1a3398c77f7f436f6e6669670000000000000000000000000000000000000000000000000000553360455560df806100c56000396000f3007f726567697374657200000000000000000000000000000000000000000000000060003514156053576020355415603257005b335415603e5760003354555b6020353360006000a233602035556020353355005b60007f756e72656769737465720000000000000000000000000000000000000000000060003514156082575033545b1560995733335460006000a2600033545560003355005b60007f6b696c6c00000000000000000000000000000000000000000000000000000000600035141560cb575060455433145b1560d25733ff5b6000355460005260206000f3'
//code needs to be a buffer
code = Buffer.from(code, 'hex')
vm.runCode({
code: code,
gasLimit: Buffer.from('ffffffff', 'hex')
}, function(err, results){
console.log('returned: ' + results.return.toString('hex'));
})
```
Also more examples can be found here
- [examples](./examples)
- [old blog post](https://wanderer.github.io/vapory/nodejs/code/2014/08/12/running-contracts-with-vm/)
# BROWSER
To build for standalone use in the browser install `browserify` and run `npm run build`. This will give you a global variable `VapVM` to use. The standalone file will be at `./dist/vaporyjs-vm.js`
# API
- [`new VM([StateTrie], [blockchain], [opts])`](#new-vmstatetrie-blockchain)
- [`VM` methods](#vm-methods)
- [`vm.runBlockchain([blockchain], [cb])`](#vmrunblockchainblockchain-cb)
- [`vm.runBlock(opts, cb)`](#vmrunblockopts-cb)
- [`vm.runTx(opts, cb)`](#vmruntxopts-cb)
- [`vm.runCode(opts, cb)`](#vmruncodeopts-cb)
- [`vm.generateCanonicalGenesis(cb)`](#vmgeneratecanonicalgenesiscb)
- [`vm.generateGenesis(cb)`](#vmgenerategenesiscb)
- [`VM` debugging hooks](#vm-debugging-hooks)
- [`vm.onStep`](#vmonstep)
### `new VM([StateTrie], [blockchain])`
Creates a new VM object
- `StateTrie` - The [Patricia Merkle Tree](https://github.com/vaporyjs/merkle-patricia-tree) that contains the state. If no trie is given the `VM` will create an in memory trie.
- `blockchain` - an instance of the [`Blockchain`](https://github.com/vapory/vaporyjs-lib/blob/master/docs/blockchain.md) If no blockchain is given a fake blockchain will be used.
- `opts`
- `enableHomestead` - a boolean that overrides the homestead settings based on blocknumber
- `activatePrecompiles` - create entries in the state tree for the precompiled contracts
### `VM` methods
#### `vm.runBlockchain(blockchain, cb)`
Process a transaction.
- `blockchain` - A [blockchain](https://github.com/vapory/vaporyjs-blockchain) that to process
- `cb` - The callback. It is given an err parameter if it fails
--------------------------------------------------------
#### `vm.runBlock(opts, cb)`
Processes the `block` running all of the transactions it contains and updating the miner's account.
- `opts.block` - The [`Block`](./block.md) to process
- `opts.generate` - a `Boolean`; whether to generate the stateRoot. If false `runBlock` will check the stateRoot of the block against the Trie
- `cb` - The callback. It is given two arguments, an `error` string containing an error that may have happened or `null`, and a `results` object with the following properties:
- `receipts` - the receipts from the transactions in the block
- `results` - an Array for results from the transactions in the block
--------------------------------------------------------
#### `vm.runTx(opts, cb)`
Process a transaction.
- `opts.tx` - A [`Transaction`](https://github.com/vapory/vaporyjs-tx) to run.
- `opts.block` - The block to which the `tx` belongs. If omitted a blank block will be used.
- `cb` - The callback. It is given two arguments, an `error` string containing an error that may have happened or `null`, and a `results` object with the following properties:
- `amountSpent` - the amount of vapor used by this transaction as a `bignum`
- `gasUsed` - the amount of gas used by the transaction
- `vm` - contains the results from running the code, if any, as described in [`vm.runCode(params, cb)`](#vmruncodeopts-cb)
--------------------------------------------------------
#### `vm.runCode(opts, cb)`
Runs EVM code
- `opts.code` - The EVM code to run given as a `Buffer`
- `opts.data` - The input data given as a `Buffer`
- `opts.value` - The value in vapor that is being sent to `opt.address`. Defaults to `0`
- `opts.block` - The [`Block`](./block.md) the `tx` belongs to. If omitted a blank block will be used.
- `opts.gasLimit` - The gas limit for the code given as a `Buffer`
- `opts.account` - The [`Account`](./account.md) that the executing code belongs to. If omitted an empty account will be used
- `opts.address` - The address of the account that is executing this code. The address should be a `Buffer` of bytes. Defaults to `0`
- `opts.origin` - The address where the call originated from. The address should be a `Buffer` of 20bits. Defaults to `0`
- `opts.caller` - The address that ran this code. The address should be a `Buffer` of 20bits. Defaults to `0`
- `cb` - The callback. It is given two arguments, an `error` string containing an error that may have happened or `null` and a `results` object with the following properties
- `gas` - the amount of gas left as a `bignum`
- `gasUsed` - the amount of gas as a `bignum` the code used to run.
- `gasRefund` - a `Bignum` containing the amount of gas to refund from deleting storage values
- `suicides` - an `Array` of accounts that have suicided.
- `suicideTo` - the account that the suicide refund should go to.
- `logs` - an `Array` of logs that the contract emitted.
- `exception` - a `boolean`, whether or not the contract encountered an exception
- `exceptionError` - a `String` describing the exception if there was one.
- `return` - a `Buffer` containing the value that was returned by the contract
--------------------------------------------------------
#### `vm.stateManager.generateCanonicalGenesis(cb)`
Generates the Canonical genesis state.
--------------------------------------------------------
#### `vm.stateManager.generateGenesis(genesisData, cb)`
Generate the genesis state.
- `genesisData` - an `Object` whose keys are addresses and values are `string`s representing initial allocation of vapor.
- `cb` - The callback
```javascript
var genesisData = {
"51ba59315b3a95761d0863b05ccc7a7f54703d99": "1606938044258990275541962092341162602522202993782792835301376",
"e4157b34ea9615cfbde6b4fda419828124b70c78": "1606938044258990275541962092341162602522202993782792835301376"
}
vm.generateGenesis(genesisData, function(){
console.log('generation done');
})
```
### `events`
All events are instances of [async-eventemmiter](https://www.npmjs.com/package/async-eventemitter). If an event handler has an arity of 2 the VM will pause until the callback is called
#### `step`
The `step` event is given an `Object` and callback. The `Object` has the following properties.
- `pc` - a `Number` representing the program counter
- `opcode` - the next opcode to be ran
- `gas` - a `bignum` standing for the amount of gasLeft
- `stack` - an `Array` of `Buffers` containing the stack.
- `storageTrie` - the storage [trie](https://github.com/vaporyjs/merkle-patricia-tree) for the account
- `account` - the [`Account`](https://github.com/vapory/vaporyjs-account) which owns the code running.
- `address` - the address of the `account`
- `depth` - the current number of calls deep the contract is
- `memory` - the memory of the VM as a `buffer`
- `cache` - The account cache. Contains all the accounts loaded from the trie. It is an instance of [functional red black tree](https://www.npmjs.com/package/functional-red-black-tree)
#### `beforeBlock`
Emits the block that is about to be processed.
#### `afterBlock`
Emits the results of the processing a block.
#### `beforeTx`
Emits the Transaction that I about to be processed.
#### `afterTx`
Emits the result of the transaction.
# TESTING
`npm test`
if you want to just run the Blockchain tests run
`./bin/tester -b`
if you want to just run the VM tests run
`./bin/tester -v`
if you want to just run the State tests run
`./bin/tester -s`
# Internal Structure
The VM processes state changes at many levels.
* runBlockchain
* for every block, runBlock
* runBlock
* for every tx, runTx
* pay miner and uncles
* runTx
* check sender balance
* check sender nonce
* runCall
* transfer gas charges
* runCall
* checkpoint state
* transfer value
* load code
* runCode
* materialize created contracts
* revert or commit checkpoint
* runCode
* iterate over code
* run op codes
* track gas usage
* OpFns
* run individual op code
* modify stack
* modify memory
* calculate fee
The opFns for `CREATE`, `CALL`, and `CALLCODE` call back up to `runCall`.
# LICENSE
[MPL-2.0](https://www.mozilla.org/MPL/2.0/)