git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 192e8e23310b0b99e63703b7d840090c2b55ddfb

added basic wasm container test

Signed-off-by: wanderer <mjbecze@gmail.com>
wanderer committed on 2/6/2018, 3:54:10 AM
Parent: 6f92591fea03c67a9e18c1daab07a4ed7d693b21

Files changed

actor.jschanged
index.jschanged
package-lock.jsonchanged
package.jsonchanged
tests/index.jschanged
tests/wasmContainer.jsadded
wasmContainer.jschanged
actor.jsView
@@ -42,9 +42,9 @@
4242 /**
4343 * Runs the startup routine for the actor
4444 */
4545 startup () {
46- return this.container.onStartup()
46+ return this.container.onStartup()
4747 }
4848
4949 /**
5050 * run the Actor with a given message
@@ -57,9 +57,8 @@
5757 this.ticks = message._fromTicks
5858 }
5959 try {
6060 this.currentMessage = message
61- // console.log(this.container.onMessage)
6261 await this.container.onMessage(message)
6362 } catch (e) {
6463 message.emit('execution:error', e)
6564 }
index.jsView
@@ -38,9 +38,10 @@
3838 state,
3939 Container,
4040 id,
4141 nonce,
42- type
42+ type,
43+ cachedb: this.tree.dag._dag
4344 })
4445
4546 await actor.startup()
4647 return actor
@@ -55,9 +56,9 @@
5556 async createActor (type, code, id = {nonce: this.nonce++, parent: null}) {
5657 const Container = this._containerTypes[type]
5758 const encoded = encodedID(id)
5859 const idHash = await this._getHashFromObj(encoded)
59- const exports = await Container.onCreation(code, idHash)
60+ const exports = await Container.onCreation(code, idHash, this.tree.dag._dag)
6061 const metaData = Actor.serializeMetaData(type)
6162
6263 // save the container in the state
6364 this.tree.set(idHash, metaData)
package-lock.jsonView
The diff is too large to show. Use a local git client to view these changes.
Old file size: 342441 bytes
New file size: 343966 bytes
package.jsonView
@@ -33,8 +33,9 @@
3333 "binary-search-insert": "^1.0.3",
3434 "buffer-pipe": "0.0.2",
3535 "events": "^1.1.1",
3636 "leb128": "0.0.4",
37+ "levelup": "^2.0.1",
3738 "reference-map": "^1.1.0",
3839 "safe-buffer": "^5.1.1",
3940 "wasm-json-toolkit": "^0.2.0",
4041 "wasm-metering": "^0.1.1"
tests/index.jsView
@@ -20,18 +20,11 @@
2020 }
2121 })
2222 return exp
2323 }
24- getFuncRef (name) {
25- return {
26- name,
27- destId: this.id
28- }
29- }
3024 onMessage (message) {
3125 return this[message.funcRef.name](...message.funcArguments)
3226 }
33-
3427 static get typeId () {
3528 return 9
3629 }
3730 }
tests/wasmContainer.jsView
@@ -1,0 +1,52 @@
1+const tape = require('tape')
2+const fs = require('fs')
3+const Message = require('../message.js')
4+const Hypervisor = require('../')
5+const WasmContainer = require('../wasmContainer.js')
6+
7+const level = require('level-browserify')
8+const RadixTree = require('dfinity-radix-tree')
9+const db = level('./testdb')
10+
11+let tester
12+
13+class TestWasmContainer extends WasmContainer {
14+ getInteface (funcRef) {
15+ const orginal = super.getInteface(funcRef)
16+ return Object.assign(orginal, {
17+ test: {
18+ check: (a, b) => {
19+ tester.equals(a, b)
20+ }
21+ }
22+ })
23+ }
24+}
25+
26+tape('basic', async t => {
27+ t.plan(2)
28+ tester = t
29+ const expectedState = {
30+ '/': Buffer.from('926de6b7eb39cfa8d7f8a44d1ef191d3bcb765a7', 'hex')
31+ }
32+
33+ const tree = new RadixTree({
34+ db: db
35+ })
36+
37+ const wasm = fs.readFileSync('./wasm/reciever.wasm')
38+
39+ const hypervisor = new Hypervisor(tree)
40+ hypervisor.registerContainer(TestWasmContainer)
41+
42+ const {exports} = await hypervisor.createActor(TestWasmContainer.typeId, wasm)
43+
44+ const message = new Message({
45+ funcRef: exports.receive,
46+ funcArguments: [5]
47+ })
48+ hypervisor.send(message)
49+
50+ const stateRoot = await hypervisor.createStateRoot()
51+ t.deepEquals(stateRoot, expectedState, 'expected root!')
52+})
wasmContainer.jsView
@@ -26,15 +26,12 @@
2626 0x60: 'func',
2727 0x40: 'block_type'
2828 }
2929
30-class Ref {
31- serialize () {}
32-}
33-
3430 class FunctionRef {
35- constructor (json, name) {
31+ constructor (name, json, id) {
3632 this.name = name
33+ this.destId = id
3734 this.args = []
3835 const typeIndex = json.typeMap[name]
3936 const type = json.type[typeIndex]
4037 const wrapper = typeCheckWrapper(type)
@@ -70,37 +67,46 @@
7067 }
7168 }
7269
7370 module.exports = class WasmContainer {
74- constructor () {
71+ constructor (actor) {
72+ this.actor = actor
7573 this.refs = new ReferanceMap()
7674 }
77- onCreation (wasm, id, cachedb) {
75+
76+ static onCreation (wasm, id, cachedb) {
77+ WebAssembly.validate(wasm)
7878 let moduleJSON = wasm2json(wasm)
79- this.json = mergeTypeSections(moduleJSON)
79+ const json = mergeTypeSections(moduleJSON)
8080 moduleJSON = wasmMetering.meterJSON(moduleJSON, {
8181 meterType: 'i32'
8282 })
83- this.wasm = json2wasm(moduleJSON)
84- this.mod = WebAssembly.Module(this.wasm)
83+ wasm = json2wasm(moduleJSON)
84+ cachedb.put(id.toString() + 'meta', json)
85+ cachedb.put(id.toString() + 'code', wasm.toString('hex'))
86+ const refs = {}
87+ Object.keys(json.typeMap).forEach(key => {
88+ refs[key] = new FunctionRef(key, json, id)
89+ })
90+ return refs
8591 }
8692
8793 sendMessage () {
8894 console.log('send')
8995 }
9096
91- onMessage (funcRef) {
97+ getInteface (funcRef) {
9298 const self = this
93- const instance = WebAssembly.Instance(this.mod, {
99+ return {
94100 func: {
95101 externalize: () => {},
96102 internalize: (ref, index) => {
97103 const {type, arg} = self.refs.get(ref)
98104 if (type !== 'funcRef') {
99105 throw new Error('invalid type')
100106 }
101107 arg.container = self
102- instance.exports.table.set(index, arg.wrapper.exports.check)
108+ this.instance.exports.table.set(index, arg.wrapper.exports.check)
103109 },
104110 catch: (ref, catchRef) => {
105111 const {funcRef} = self.refs.get(ref, FunctionRef)
106112 const {funcRef: catchFunc} = self.refs.get(ref, FunctionRef)
@@ -151,27 +157,66 @@
151157 throw new Error('out of gas! :(')
152158 }
153159 }
154160 }
155- })
156- const args = funcRef.args.map(arg => {
157- if (nativeTypes.has(arg.type)) {
158- return arg.arg
161+ }
162+ }
163+
164+ onMessage (message) {
165+ const funcRef = message.funcRef
166+ const intef = this.getInteface(funcRef)
167+ this.instance = WebAssembly.Instance(this.mod, intef)
168+ const args = message.funcArguments.map(arg => {
169+ if (typeof arg === 'number') {
170+ return arg
159171 } else {
160172 return this.refs.add(arg)
161173 }
162174 })
163- instance.exports[funcRef.name](...args)
175+ this.instance.exports[funcRef.name](...args)
164176 }
165177
166178 getFuncRef (name, send) {
167179 const funcRef = new FunctionRef(this.json, name, send)
168180 return funcRef
169181 }
182+
183+ async onStartup () {
184+ let [json, wasm] = await Promise.all([
185+ new Promise((resolve, reject) => {
186+ this.actor.cachedb.get(this.actor.id.toString() + 'meta', (err, json) => {
187+ if (err) {
188+ reject(err)
189+ } else {
190+ resolve(json)
191+ }
192+ })
193+ }),
194+ new Promise((resolve, reject) => {
195+ this.actor.cachedb.get(this.actor.id.toString() + 'code', (err, wasm) => {
196+ if (err) {
197+ reject(err)
198+ } else {
199+ resolve(wasm)
200+ }
201+ })
202+ })
203+ ])
204+ wasm = Buffer.from(wasm, 'hex')
205+ this.mod = WebAssembly.Module(wasm)
206+ this.json = json
207+ }
208+
209+ static get typeId () {
210+ return 9
211+ }
170212 }
171213
172214 function mergeTypeSections (json) {
173- const typeInfo = {}
215+ const typeInfo = {
216+ typeMap: [],
217+ type: []
218+ }
174219 let typeSection = {
175220 'entries': []
176221 }
177222 let importSection = {

Built with git-ssb-web