Skip to content
This repository has been archived by the owner on Mar 19, 2018. It is now read-only.

Commit

Permalink
added asserts
Browse files Browse the repository at this point in the history
  • Loading branch information
wanderer committed Mar 28, 2015
1 parent d5b6a1e commit f3d9e56
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 63 deletions.
74 changes: 61 additions & 13 deletions lib/vm/cache.js
@@ -1,21 +1,69 @@
const Tree = require('functional-red-black-tree');
const Set = require('es6-set');
const Account = require('../account.js');

var Cache = module.exports = function() {
var Cache = module.exports = function(trie) {
this._cache = Tree();
this._checkpoints = [];
this._trie = trie;
}

Cache.prototype.populateCache = function(accounts, cb) {
//shim till async supports iterators
var accountArr = [];
accounts.forEach(function(val) {
if (val) accountArr.push(val);
})
Cache.prototype.put = function(key, val) {
key = key.toString('hex');

async.eachSeries(accountArr, function(acnt, done) {
console.log(acnt);
self.trie.get(new Buffer(acnt, 'hex'), function(err, val) {
self.cache = self.cache.insert(acnt, val);
done();
var it = this._cache.find(key);
if(it.node){
this._cache = it.update(val);
}else{
this._cache = this._cache.insert(key, val);
}
}

Cache.prototype.get = function(key){
key = key.toString('hex');

var it = this._cache.find(key)
if(it.node){
return it.value;
}else{
return new Account();
}
}

Cache.prototype.getOrLoad = function(key, cb){
var self = this;

if(!key){
return cb();
}

key = key.toString('hex');

var it = this._cache.find(key)
if(it.node){
cb(null, it.value);
}else{
this._trie.get(new Buffer(key, 'hex'), function(err, raw){
var account = new Account(raw);
self._cache = self._cache.insert(key, account);
cb(err, account);
});
}, cb);
}
}

Cache.prototype.checkpoint = function(){
this._checkpoints.push(this._cache)
}

Cache.prototype.revert = function(){
this._cache = this._checkpoints.pop(this._cache)
}

Cache.prototype.commit = function(){
this._checkpoints.pop();
}

Cache.prototype.del = function(key){
key = key.toString('hex');
this._cache = this._cache.remove(key);
}
2 changes: 2 additions & 0 deletions lib/vm/index.js
Expand Up @@ -7,6 +7,7 @@ const ethUtil = require('ethereumjs-util');
const EventEmitter = require('events').EventEmitter;
const fs = require('fs');
const path = require('path');
const Cache = require('./cache.js');

/**
* @constructor
Expand All @@ -19,6 +20,7 @@ var VM = module.exports = function(trie, blockchain) {

this.blockchain = blockchain;
this.trie = trie;
this.cache = new Cache(trie);
};

util.inherits(VM, EventEmitter);
Expand Down
30 changes: 27 additions & 3 deletions lib/vm/runBlock.js
Expand Up @@ -5,6 +5,7 @@ const rlp = require('rlp');
const Trie = require('merkle-patricia-tree');
const Set = require('es6-set');
const BN = require('bn.js');
const assert = require('assert');

/**
* process the transaction in a block and pays the miners
Expand Down Expand Up @@ -54,12 +55,13 @@ module.exports = function(opts, cb) {
})

async.eachSeries(accountArr, function(acnt, done) {
self.trie.get(new Buffer(acnt, 'hex'), function(err, val) {
self.cache = self.cache.insert(acnt, val);
acnt = new Buffer(acnt, 'hex');
self.trie.get(acnt, function(err, val) {
val = new Account(val);
self.cache.put(acnt, val);
done();
});
}, cb);

}

/**
Expand Down Expand Up @@ -112,9 +114,16 @@ module.exports = function(opts, cb) {
},
//get the miners account
function getMinerAccount(cb) {

trie.get(block.header.coinbase, function(err, rawAccount) {
account = new Account(rawAccount);
//add the amount spent on gas to the miner's account
var c = self.cache.get(block.header.coinbase);
assert(account.balance.toString('hex') === c.balance.toString('hex'))
assert(account.nonce.toString('hex') === c.nonce.toString('hex'))
assert(account.codeHash.toString('hex') === c.codeHash.toString('hex'))
assert(account.stateRoot.toString('hex') === c.stateRoot.toString('hex'))

account.balance = new BN(account.balance)
.add(results.amountSpent);

Expand All @@ -126,11 +135,14 @@ module.exports = function(opts, cb) {
block.header.bloom = bloom.bitvector;
}

self.cache.put(block.header.coinbase, account);

//save the miner's account
trie.put(block.header.coinbase, account.serialize(), function(err) {
cb3(err);
});
},
//flush here
//create the tx receipt
function createTxReceipt(cb3) {
var txLogs = results.vm.logs ? results.vm.logs : [];
Expand All @@ -148,7 +160,15 @@ module.exports = function(opts, cb) {
//get the miners account TODO: why twice?
function getMinerAccount(cb) {
trie.get(block.header.coinbase, function(err, rawAccount) {

account = new Account(rawAccount);
var c = self.cache.get(block.header.coinbase);

assert(account.balance.toString('hex') === c.balance.toString('hex'))
assert(account.nonce.toString('hex') === c.nonce.toString('hex'))
assert(account.codeHash.toString('hex') === c.codeHash.toString('hex'))
assert(account.stateRoot.toString('hex') === c.stateRoot.toString('hex'))

cb(err);
});
}
Expand All @@ -171,12 +191,14 @@ module.exports = function(opts, cb) {

} else {
trie.get(uncle.coinbase, function(err, rawAccount) {

if (!err) {
var uncleAccount = new Account(rawAccount);
uncleAccount.balance = new BN(uncleAccount.balance)
.add(uncleReward)
.toBuffer();

self.cache.put(uncle.coinbase, uncleAccount)
trie.put(uncle.coinbase, uncleAccount.serialize(), cb2);

} else {
Expand All @@ -193,11 +215,13 @@ module.exports = function(opts, cb) {
.add(minerReward)
.add(r); //add the accumlated nephewReward

self.cache.put(block.header.coinbase, account)
trie.put(block.header.coinbase, account.serialize(), cb);
}

//run everything
async.series([
populateCache,
getMinerAccount,
processTransactions,
payUncles,
Expand Down
20 changes: 18 additions & 2 deletions lib/vm/runCall.js
Expand Up @@ -2,6 +2,7 @@ const async = require('async');
const BN = require('bn.js');
const Account = require('../account');
const utils = require('ethereumjs-util');
const assert = require('assert');

/**
* runs a CALL operation
Expand Down Expand Up @@ -30,6 +31,7 @@ module.exports = function(opts, cb) {
var gasUsed = new BN(0);

this.trie.checkpoint();
this.cache.checkpoint();

//set default values
if (!opts.value) {
Expand All @@ -40,7 +42,6 @@ module.exports = function(opts, cb) {
fromAccount.balance = new Buffer((new BN(fromAccount.balance).sub(opts.value)).toArray());
}


function getToAccount(cb2) {
//get receiver's account
if (!opts.to) {
Expand All @@ -53,7 +54,15 @@ module.exports = function(opts, cb) {
//else load the to account
data = opts.data;
self.trie.get(opts.to, function(err, account) {

toAccount = new Account(account);

var c = self.cache.get(opts.to);
assert(toAccount.balance.toString('hex') === c.balance.toString('hex'))
assert(toAccount.nonce.toString('hex') === c.nonce.toString('hex'))
assert(toAccount.codeHash.toString('hex') === c.codeHash.toString('hex'))
assert(toAccount.stateRoot.toString('hex') === c.stateRoot.toString('hex'))

cb2(err);
});
}
Expand Down Expand Up @@ -133,8 +142,10 @@ module.exports = function(opts, cb) {
gasUsed = results.gasUsed;

if (results.exceptionErr) {
self.cache.revert();
self.trie.revert(cb2);
} else {
self.cache.commit();
self.trie.commit(cb2);
}
});
Expand All @@ -154,17 +165,22 @@ module.exports = function(opts, cb) {

function saveToAccount(cb2) {
//save the to account
self.cache.put(opts.to, toAccount);
self.trie.put(opts.to, toAccount.serialize(), cb2);
}

async.series([
//save the current account. We need to do this becase we could be calling recursivly
async.apply(self.trie.put.bind(self.trie), opts.caller, opts.account.serialize()),
function(done){
self.cache.put(opts.caller, opts.account);
self.trie.put(opts.caller, opts.account.serialize(), done);
},
getToAccount,
loadCode,
runCode,
function(done){
if(vmResults.exceptionErr){
self.cache.put(opts.caller, opts.account);
self.trie.put(opts.caller, opts.account.serialize(), done);
}else{
done();
Expand Down

0 comments on commit f3d9e56

Please sign in to comment.