git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 40fce8207151c8b05af5d4bd34e82751421a7893

first test passing

wanderer committed on 4/24/2017, 4:10:41 PM
Parent: d6ecef73fd6edc80197140774535f1adea617314

Files changed

index.jschanged
kernel.jschanged
package.jsonchanged
port.jschanged
portManager.jschanged
tests/index.jschanged
index.jsView
@@ -14,18 +14,20 @@
1414 Object.assign(this._opts, opts)
1515 }
1616
1717 async getInstance (port) {
18- const id = await this.generateID(port.id)
18+ const id = await this.generateID(port)
1919 let kernel = this._vmInstances.get(id)
2020 if (!kernel) {
2121 // load the container from the state
2222 await this.graph.tree(port, 2)
2323
2424 // create a new kernel instance
25+ const VM = this._opts.VMs[port.type]
2526 const opts = Object.assign({
2627 state: port.vm,
27- id: port.id
28+ id: port.id,
29+ VM: VM
2830 }, this._opts)
2931
3032 kernel = new Kernel(opts)
3133 await kernel.start()
@@ -38,10 +40,9 @@
3840 }
3941
4042 async send (port, message) {
4143 const vm = await this.getInstance(port)
42- const id = await this.generateID(port.id)
43- message._fromPort = id
44+ message._fromPort = 'root'
4445 vm.queue(message)
4546 }
4647
4748 // given a port, wait untill its source contract has reached the threshold
@@ -52,16 +53,20 @@
5253 return kernel
5354 }
5455
5556 async createStateRoot (port, ticks) {
56- const kernel = await this.wait(port, ticks)
57- return this.graph.flush(kernel.state)
57+ await this.wait(port, ticks)
58+ return this.graph.flush(port)
5859 }
5960
6061 async generateID (port) {
61- let id = Buffer.concat([port.nonce, port.parent])
62- id = await crypto.subtle.digest('SHA-256', id)
63- return new Buffer(id).toString('hex')
62+ if (typeof port === 'object') {
63+ let id = Buffer.concat([port.id.nonce, port.id.parent])
64+ id = await crypto.subtle.digest('SHA-256', id)
65+ return new Buffer(id).toString('hex')
66+ } else {
67+ return port
68+ }
6469 }
6570
6671 addVM (type, vm) {
6772 this._opts.VMs[type] = vm
kernel.jsView
@@ -2,16 +2,16 @@
22 const EventEmitter = require('events')
33 const BN = require('bn.js')
44 const PortManager = require('./portManager.js')
55
6-const VMSTATES = ['idle', 'running', 'result']
7-
86 module.exports = class Kernel extends EventEmitter {
97 constructor (opts) {
108 super()
119 this._opts = opts
12- this._vmStateIndex = 0
10+ this.vmState = 'idle'
11+ this.ticks = 0
1312 this.ports = new PortManager(this)
13+ this.vm = new opts.VM(this)
1414 this._waitingQueue = new PriorityQueue((a, b) => {
1515 return a.threshold > b.threshold
1616 })
1717 this.on('result', this._runNextMessage)
@@ -20,18 +20,13 @@
2020 start () {
2121 return this.ports.start()
2222 }
2323
24- _updateVmState (message) {
25- this._vmStateIndex++
26- const vmState = VMSTATES[this._stateVmIndex]
27- this._emit(vmState, message)
24+ _updateVmState (state, message) {
25+ this.vmState = state
26+ this.emit(this.vmState, message)
2827 }
2928
30- get vmState () {
31- return VMSTATES[this._stateVmIndex]
32- }
33-
3429 queue (message) {
3530 this.ports.queue(message)
3631 if (this.vmState === 'idle') {
3732 this._runNextMessage()
@@ -42,9 +37,9 @@
4237 this.ports.getNextMessage(this.ticks).then(message => {
4338 if (message) {
4439 this.run(message)
4540 } else {
46- this._updateState()
41+ this._updateVmState('idle', message)
4742 }
4843 })
4944 }
5045
@@ -52,15 +47,15 @@
5247 * run the kernels code with a given enviroment
5348 * The Kernel Stores all of its state in the Environment. The Interface is used
5449 * to by the VM to retrive infromation from the Environment.
5550 */
56- async run (message, imports = this.imports) {
51+ async run (message) {
52+ this._updateVmState('running', message)
5753 // shallow copy
5854 const oldState = Object.assign({}, this._opts.state)
5955 let result
60- this._updateState(message)
6156 try {
62- result = await this._vm.run(message, this, imports) || {}
57+ result = await this.vm.run(message) || {}
6358 } catch (e) {
6459 result = {
6560 exception: true,
6661 exceptionError: e
@@ -72,18 +67,18 @@
7267 clearObject(this._opts.state)
7368 Object.assign(this._opts.state, oldState)
7469 }
7570
76- this._updateVmState(result)
71+ this._updateVmState('result', result)
7772 return result
7873 }
7974
8075 // returns a promise that resolves once the kernel hits the threshould tick
8176 // count
8277 async wait (threshold) {
83- if (this._vmState === 'idle' && threshold > this.ticks) {
78+ if (this.vmState === 'idle' && threshold > this.ticks) {
8479 // the cotract is at idle so wait
85- return this.portManager.wait(threshold)
80+ return this.ports.wait(threshold)
8681 } else {
8782 return new Promise((resolve, reject) => {
8883 if (threshold <= this.ticks) {
8984 resolve(this.ticks)
@@ -106,9 +101,9 @@
106101
107102 createPort () {
108103 const nonce = new BN(this.nonce)
109104 nonce.iaddn(1)
110- this.nonce = nonce.toArrayLike(Uint8Array)
105+ this.nonce = nonce.toArrayLike(Buffer)
111106 return {
112107 id: {
113108 '/': {
114109 nonce: this.nonce,
@@ -121,8 +116,9 @@
121116 }
122117 }
123118
124119 async send (port, message) {
120+ message._ticks = this.ticks
125121 return this._opts.hypervisor.send(port, message)
126122 }
127123 }
128124
package.jsonView
@@ -2,9 +2,9 @@
22 "name": "primea-hypervisor",
33 "version": "0.0.0",
44 "description": "this is a JS implemention of the primea hypervisor",
55 "scripts": {
6- "coverage": "node --harmony ./node_modules/istanbul/lib/cli.js cover ./tests/apiTests.js",
6+ "coverage": "node --harmony ./node_modules/istanbul/lib/cli.js cover ./tests/index.js",
77 "coveralls": "npm run coverage && coveralls <coverage/lcov.info",
88 "lint": "standard",
99 "test": "node --harmony --expose-wasm ./tests/interfaceRunner.js",
1010 "build": "node ./tests/buildTests.js && ./tools/wabt/out/wast2wasm ./wasm/interface.wast -o ./wasm/interface.wasm"
port.jsView
@@ -5,9 +5,9 @@
55 this.ticks = 0
66 }
77
88 queue (message) {
9- this.ticks = message.ticks
9+ this.ticks = message._ticks
1010 if (this._resolve) {
1111 return this._resolve(message)
1212 } else {
1313 this._queue.push(message)
@@ -31,7 +31,7 @@
3131 return this._queue[0]
3232 }
3333
3434 shift () {
35- this._queue.shift()
35+ return this._queue.shift()
3636 }
3737 }
portManager.jsView
@@ -1,6 +1,28 @@
11 const Port = require('./port.js')
22
3+// decides which message to go firts
4+function messageArbiter (portA, portB) {
5+ const a = portA.peek()
6+ const b = portB.peek()
7+
8+ if (!a) {
9+ return b
10+ } else if (!b) {
11+ return a
12+ }
13+
14+ const aGasPrice = a.resources.gasPrice
15+ const bGasPrice = b.resources.gasPrice
16+ if (a.ticks !== b.ticks) {
17+ return a.ticks < b.ticks ? a : b
18+ } else if (aGasPrice === bGasPrice) {
19+ return a.hash() > b.hash() ? a : b
20+ } else {
21+ return aGasPrice > bGasPrice ? a : b
22+ }
23+}
24+
325 module.exports = class PortManager {
426 constructor (kernel) {
527 this.kernel = kernel
628 this.hypervisor = kernel._opts.hypervisor
@@ -17,13 +39,13 @@
1739 })
1840 })
1941
2042 // create the parent port
21- ports.push(this.hypervisor.generateID(this.kernel._opts.id).then(id => {
22- return [id, new Port('parent')]
23- }))
2443 ports = await Promise.all(ports)
2544 this._portMap = new Map(ports)
45+ // add the parent port
46+ const parent = this.kernel._opts.id.parent.length === 0 ? 'root' : this.kernel._opts.id.parent
47+ this._portMap.set(parent, new Port('parent'))
2648 }
2749
2850 queue (message) {
2951 this._portMap.get(message.fromPort).queue(message)
@@ -48,22 +70,21 @@
4870 return this._portMap.get(id)
4971 }
5072
5173 async getParent () {
52- const id = await this.hypervisor.generateID(this.kernel._opts.id)
74+ const id = await this.hypervisor.generateID(this.kernel._opts)
5375 return this._portMap.get(id)
5476 }
5577
5678 // waits till all ports have reached a threshold tick count
5779 async wait (threshold) {
5880 // find the ports that have a smaller tick count then the threshold tick count
59- const unkownPorts = [...this._ports].filter((id, port) => {
60- const message = port.peek()
61- return !message || message.ticks < threshold
81+ const unkownPorts = [...this._portMap].filter(([id, port]) => {
82+ return port._ticks < threshold
6283 })
6384
64- const promises = unkownPorts.map(port => {
65- this.hypervisor.wait(port, threshold).then(ticks => {
85+ const promises = unkownPorts.map(([id, port]) => {
86+ this.hypervisor.wait(id, threshold).then(ticks => {
6687 // update the port's tick count
6788 port.ticks = ticks
6889 })
6990 })
@@ -71,29 +92,8 @@
7192 }
7293
7394 async getNextMessage (ticks) {
7495 await this.wait(ticks)
75- return [...this._portMap].reduce(messageArbiter).shift()
96+ return [...this._portMap].reduce(messageArbiter)[1].shift()
7697 }
7798 }
7899
79-// decides which message to go firts
80-function messageArbiter (portA, portB) {
81- const a = portA.peek()
82- const b = portB.peek()
83-
84- if (!a) {
85- return b
86- } else if (!b) {
87- return a
88- }
89-
90- const aGasPrice = a.resources.gasPrice
91- const bGasPrice = b.resources.gasPrice
92- if (a.ticks !== b.ticks) {
93- return a.ticks < b.ticks ? a : b
94- } else if (aGasPrice === bGasPrice) {
95- return a.hash() > b.hash() ? a : b
96- } else {
97- return aGasPrice > bGasPrice ? a : b
98- }
99-}
tests/index.jsView
@@ -9,37 +9,41 @@
99 })
1010
1111 node.on('start', () => {
1212 tape.only('basic', async t => {
13- const testVM = {
14- run (message) {
15- console.log('made it!!!!')
13+ const message = new Message()
14+ class testVM {
15+ run (m) {
16+ t.true(m === message, 'should recive a message')
17+ t.end()
1618 }
1719 }
1820
1921 try {
2022 const state = {
2123 id: {
22- nonce: new Uint8Array([0]),
23- parent: new Uint8Array()
24+ nonce: new Buffer([0]),
25+ parent: new Buffer([])
2426 },
2527 type: 'test',
2628 vm: {
2729 ports: {}
2830 }
2931 }
3032
31- const hypervisor = new Hypervisor(node.dag)
33+ const expectedState = { '/': 'zdpuApqUjZFhw8LTkw8gXAbVcqc5Y7TsbTVadU879TgucoqSF' }
34+
35+ const hypervisor = new Hypervisor({
36+ dag: node.dag
37+ })
3238 hypervisor.addVM('test', testVM)
3339
34- const message = new Message()
3540 await hypervisor.send(state, message)
3641
3742 await hypervisor.createStateRoot(state, Infinity)
38- console.log(state)
43+ t.deepEquals(state, expectedState, 'expected')
3944
4045 node.stop(() => {
41- t.end()
4246 process.exit()
4347 })
4448 } catch (e) {
4549 console.log(e)

Built with git-ssb-web