git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 60b86f48100a3b8a9db14f54689cabe117acdff3

fix tests

wanderer committed on 3/1/2017, 2:29:46 PM
Parent: 8ced6c46cc8f744d128a65d00c117a79e68918b8

Files changed

EVMinterface.jschanged
hypervisor.jschanged
index.jschanged
message.jschanged
port.jschanged
portManager.jschanged
tests/interfaceRunner.jschanged
EVMinterface.jsView
@@ -458,32 +458,32 @@
458458 * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
459459 */
460460 _call (gasHigh, gasLow, addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, cbIndex) {
461461 this.takeGas(40)
462-
463462 const gas = from64bit(gasHigh, gasLow)
464463 // Load the params from mem
465- const address = [common.PARENT, ...this.getMemory(addressOffset, ADDRESS_SIZE_BYTES)]
464+ const address = [common.PARENT, common.PARENT, ...this.getMemory(addressOffset, ADDRESS_SIZE_BYTES)]
466465 const value = new U256(this.getMemory(valueOffset, U128_SIZE_BYTES))
467466
468467 // Special case for non-zero value; why does this exist?
469468 if (!value.isZero()) {
470469 this.takeGas(9000 - 2300 + gas)
471470 this.takeGas(-gas)
472471 }
473472
474- // should be
475- let opPromise = this.kernel.send(new Message({
473+ const message = new Message({
476474 to: address,
477475 value: value
478- }))
479- .catch(() => {
480- // why does this exist?
481- this.takeGas(25000)
482476 })
483477
478+ const messagePromise = this.kernel.send(message).then(result => {
479+ if (result.exception) {
480+ this.takeGas(25000)
481+ }
482+ })
483+
484484 // wait for all the prevouse async ops to finish before running the callback
485- this.api.pushOpsQueue(opPromise, cbIndex, () => {
485+ this.api.pushOpsQueue(messagePromise, cbIndex, () => {
486486 return 1
487487 })
488488 }
489489
hypervisor.jsView
@@ -1,21 +1,21 @@
11 const Kernel = require('./index.js')
22 const Vertex = require('merkle-trie')
3-const Block = require('./deps/block.js')
4-const blockchain = require('./fakeBlockChain.js')
3+// const Block = require('./deps/block.js')
4+// const blockchain = require('./fakeBlockChain.js')
55 const codeHandlers = require('./codeHandler.js')
66
77 module.exports = class Hypervisor {
88 constructor (state = new Vertex()) {
99 this.state = state
10- if (state.isEmpty) {
11- state.set('block', new Vertex({
12- value: new Block()
13- }))
14- state.set('blockchain', new Vertex({
15- value: blockchain
16- }))
17- }
10+ // if (state.isEmpty) {
11+ // state.set('block', new Vertex({
12+ // value: new Block()
13+ // }))
14+ // state.set('blockchain', new Vertex({
15+ // value: blockchain
16+ // }))
17+ // }
1818 this.root = new Kernel({
1919 state: state
2020 })
2121 }
@@ -26,10 +26,9 @@
2626 }))
2727 }
2828
2929 send (message) {
30- this.root.send(message)
31- return message.result()
30+ return this.root.send(message)
3231 }
3332
3433 addVM (type, handler) {
3534 codeHandlers.handlers.type = handler
index.jsView
@@ -3,30 +3,34 @@
33 const PortManager = require('./portManager.js')
44 const StateInterface = require('./stateInterface.js')
55 const imports = require('./EVMinterface.js')
66 const codeHandler = require('./codeHandler.js')
7-const common = require('./common.js')
87
98 module.exports = class Kernel extends EventEmitter {
109 constructor (opts = {}) {
1110 super()
11+ // set up the state
1212 const state = this.state = opts.state || new Vertex()
1313 this.stateInterface = new StateInterface(state)
14- this.code = opts.code || state.value
1514 this.path = state.path
15+
16+ // set up the vm
1617 this.imports = opts.imports || [imports]
17- this.ports = new PortManager(state, opts.parent, Kernel)
18+ this._vm = (opts.codeHandler || codeHandler).init(opts.code || state.value)
19+ this._state = 'idle'
20+
21+ // set up ports
22+ this.ports = new PortManager(state, opts.parentPort, Kernel)
1823 this._sentAtomicMessages = []
19- this._vm = (opts.codeHandler || codeHandler).init(this.code)
20- this._state = 'idle'
2124 this.ports.on('message', index => {
2225 this.runNextMessage(index)
2326 })
2427 }
2528
2629 runNextMessage (index = 0) {
2730 return this.ports.peek(index).then(message => {
28- if (message && (message.isCyclic(this) || this._state === 'idle')) {
31+ if (message && (message._isCyclic(this) || this._state === 'idle')) {
32+ this._currentMessage = message
2933 this.ports.remove(index)
3034 return this.run(message)
3135 } else {
3236 this._state = 'idle'
@@ -40,34 +44,35 @@
4044 * The Kernel Stores all of its state in the Environment. The Interface is used
4145 * to by the VM to retrive infromation from the Environment.
4246 */
4347 async run (message, imports = this.imports) {
44- function revert () {
48+ function revert (oldState) {
4549 // revert the state
4650 this.state.set([], oldState)
4751 // revert all the sent messages
4852 for (let msg in this._sentAtomicMessages) {
4953 msg.revert()
5054 }
51- this.runNextMessage(0)
5255 }
5356
5457 const oldState = this.state.copy()
5558 let result
5659 this._state = 'running'
5760 try {
5861 result = await this._vm.run(message, this, imports) || {}
5962 } catch (e) {
60- console.log(e)
6163 result = {
62- exception: true
64+ exception: true,
65+ exceptionError: e
6366 }
6467 }
65- if (result.execption) {
66- // failed messages
67- revert()
68- } else if (message.atomic) {
69- // messages
68+
69+ if (message.atomic) {
70+ // if we trapped revert all the sent messages
71+ if (result.execption) {
72+ // revert to the old state
73+ revert(oldState)
74+ }
7075 message._finish()
7176 message.result().then(result => {
7277 if (result.execption) {
7378 revert()
@@ -75,9 +80,9 @@
7580 this.runNextMessage(0)
7681 }
7782 })
7883
79- if (message.hops === message.to.length) {
84+ if (message.hops === message.to.length || result.exception) {
8085 message._respond(result)
8186 }
8287 } else {
8388 // non-atomic messages
@@ -86,25 +91,16 @@
8691 return result
8792 }
8893
8994 async send (message) {
90- let portName = message.nextPort()
91- // replace root with parent path to root
92- if (portName === common.ROOT) {
93- message.to.shift()
94- message.to = new Array(this.path.length).fill(common.PARENT).concat(message.to)
95- portName = common.PARENT
96- }
97- message.addVistedKernel(this)
98- this.lastMessage = message
99- // console.log(portName, message)
100- const port = await this.ports.get(portName)
101- // save the atomic messages for possible reverts
10295 if (message.atomic) {
96+ // record that this message has traveled thourgh this kernel. This is used
97+ // to detect re-entry
98+ message._visited(this, this._currentMessage)
99+ // recoded that this message was sent, so that we can revert it if needed
103100 this._sentAtomicMessages.push(message)
104101 }
105- port.send(message)
106- return message.result()
102+ return this.ports.send(message)
107103 }
108104
109105 shutdown () {}
110106 }
message.jsView
@@ -13,38 +13,37 @@
1313 gasPrices: new U256(0)
1414 }
1515 Object.assign(this, defaults, opts)
1616 this.hops = 0
17- this._vistedKernels = []
17+ this._visitedKernels = []
1818 this._resultPromise = new Promise((resolve, reject) => {
1919 this._resolve = resolve
2020 })
2121 }
2222
23- _finish () {
24- if (this.atomic) {
25- this._vistedKernels.pop()
26- }
23+ result () {
24+ return this._resultPromise
2725 }
2826
27+ nextPort () {
28+ return this.to[this.hops]
29+ }
30+
2931 _respond (result) {
3032 this._resolve(result)
3133 }
3234
33- result () {
34- return this._resultPromise
35+ _finish () {
36+ this._visitedKernels.pop()
3537 }
3638
37- nextPort () {
38- return this.to[this.hops++]
39- }
40-
41- addVistedKernel (kernel) {
42- if (this.atomic) {
43- this._vistedKernels.push(kernel)
39+ _visited (kernel, currentMessage) {
40+ if (currentMessage && this !== currentMessage) {
41+ this._visitedKernels = currentMessage._visitedKernels
4442 }
43+ this._visitedKernels.push(kernel)
4544 }
4645
47- isCyclic (kernel) {
48- return this.atomic && this._vistedKernels.some(process => process === kernel)
46+ _isCyclic (kernel) {
47+ return this.atomic && this._visitedKernels.some(process => process === kernel)
4948 }
5049 }
port.jsView
@@ -15,8 +15,9 @@
1515 }
1616 }
1717
1818 async send (message) {
19+ message.hops++
1920 this.destPort.recieve(message)
2021 }
2122
2223 async recieve (message) {
portManager.jsView
@@ -24,9 +24,8 @@
2424 this.emit('message', index)
2525 }
2626
2727 async get (name) {
28- console.log(name)
2928 let port = this.cache.get(name)
3029 if (!port) {
3130 port = new Port(name)
3231 port.on('message', message => {
@@ -35,9 +34,9 @@
3534 // create destination kernel
3635 const state = await this.state.get(name)
3736 const destKernel = new this.Kernel({
3837 state: state,
39- parent: port
38+ parentPort: port
4039 })
4140
4241 // shutdown the kernel when it is done doing it work
4342 destKernel.on('idle', () => {
@@ -60,8 +59,15 @@
6059 remove (index) {
6160 return this._queue.splice(index, index + 1)
6261 }
6362
63+ async send (message) {
64+ let portName = message.nextPort()
65+ const port = await this.get(portName)
66+ port.send(message)
67+ return message.result()
68+ }
69+
6470 close () {
6571 for (let port in this.cache) {
6672 port.emit('close')
6773 }
tests/interfaceRunner.jsView
@@ -13,9 +13,9 @@
1313
1414 const dir = path.join(__dirname, '/interface')
1515 // get the test names
1616 let tests = fs.readdirSync(dir).filter((file) => file.endsWith('.wast'))
17-tests = ['call.wast']
17+// tests = ['call.wast']
1818
1919 runTests(tests)
2020
2121 function runTests (tests) {
@@ -67,13 +67,10 @@
6767 message.gas = 1000000
6868
6969 try {
7070 await hypervisor.send(message)
71- console.log('done')
7271 } catch (e) {
7372 t.fail('Exception: ' + e)
74- console.error('FAIL')
75- console.error(e)
7673 } finally {
7774 t.pass(testName)
7875 }
7976 t.end()

Built with git-ssb-web