git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 798d22f70346b2550010f853c9c3582ae86e1f35

added index/package/etc

wanderer committed on 7/11/2016, 2:57:15 PM
Parent: 5eeb3318e23f80e97b5a32ea49d43cbd9fa8560e

Files changed

tests/runner.jsadded
README.mdadded
index.jsadded
interface.jsadded
package.jsonadded
tests/runner.jsView
@@ -1,0 +1,39 @@
1+'use strict'
2+const tape = require('tape')
3+const fs = require('fs')
4+const cp = require('child_process')
5+
6+// This
7+const Environment = require('./environment.js')
8+const Interface = require('../interface.js')
9+// console.log('tes1 11')
10+// get the test names
11+let tests = fs.readdirSync('.').filter((file) => file.endsWith('.wast'))
12+// tests = ['balance.wast']
13+// run the tests
14+for (let testName of tests) {
15+ testName = testName.split('.')[0]
16+ tape(testName, (t) => {
17+ // Compile Command
18+ cp.execSync(`../../evm-wasm-transcompiler/deps/sexpr-wasm-prototype/out/sexpr-wasm ./${testName}.wast -o ./${testName}.wasm`)
19+ const buffer = fs.readFileSync(`./${testName}.wasm`)
20+ const envData = fs.readFileSync(`./${testName}.json`)
21+
22+ const environment = new Environment(envData)
23+ const ethInterface = new Interface(environment)
24+
25+ try {
26+ const mod = Wasm.instantiateModule(buffer, {'ethereum': ethInterface})
27+ ethInterface.setModule(mod)
28+ // ethInterface.address(0)
29+ // console.log(ethInterface.environment);
30+ mod.exports.test()
31+ } catch (e) {
32+ console.error('FAIL')
33+ console.error(e)
34+ } finally {
35+ console.log('done')
36+ }
37+ t.end()
38+ })
39+}
README.mdView
@@ -1,0 +1,14 @@
1+# JS prototype
2+
3+The js prototype just implements the Ethereum interface. It uses v8 to run the WASM code.
4+
5+## Run tests
6+The tests are written in wasm's text format (.wast) which are then compiled into binary format and ran in v8.
7+
8+To run the test you need
9+* download the submodules.
10+* compile [v8](https://github.com/v8/v8), which will be in the v8 folder, Instuctions [here](https://github.com/v8/v8/wiki/Building-with-Gyp)
11+* compile the [sexpr-wasm-prototype](https://github.com/WebAssembly/sexpr-wasm-prototype) which will be in the sexpr-wasm-prototype folder
12+ `cd sexpr-wasm-prototype && make`
13+* `npm install`
14+* `npm test`
index.jsView
@@ -1,0 +1,36 @@
1+const Environment = require('./testEnvironment.js')
2+const Interface = require('./interface.js')
3+
4+module.exports = class BaseStateTranitions {
5+ // runs some code in the VM
6+ constructor (state) {
7+ this.state = state
8+ }
9+
10+ // handles running code
11+ static codeHandler (code, environment) {
12+ const ethInterface = new Interface(environment)
13+ const instance = Wasm.instantiateModule(code, ethInterface)
14+ ethInterface.setModule(ethInterface)
15+ return instance
16+ }
17+
18+ // loads code from the merkle trie and run it
19+ // callHandler (msg, code) {
20+ // const instance = Wasm.instantiateModule(code, interface)
21+ // interface.setModule(instance)
22+ // return instance
23+ // }
24+
25+ // Builtin contracts
26+ // run code
27+
28+ // run tx
29+ // runTx () {}
30+
31+ // run block
32+ // runBlock () {}
33+
34+ // run blockchain
35+ // runBlockchain () {}
36+}
interface.jsView
@@ -1,0 +1,356 @@
1+const constants = require('./constants.js')
2+
3+// function.bind is not working corretly whith Wasm imports. So instead create
4+// a global for now. TODO REMOVE
5+let ENV
6+let MOD
7+// The interface exposed to the WebAessembly Core
8+module.exports = class Interface {
9+ constructor (environment) {
10+ ENV = this.environment = environment
11+ }
12+
13+ setModule (mod) {
14+ this.module = MOD = mod
15+ }
16+
17+ debugPrint (a, b) {
18+ console.log(a)
19+ }
20+
21+ memPrint () {
22+ console.log((new Uint8Array(MOD.exports.memory)).toString())
23+ }
24+
25+ /**
26+ * Subtracts an amount to the gas counter
27+ * @param {integer} amount the amount to subtract to the gas counter
28+ */
29+ addGas (amount) {
30+ if (amount > 0) {
31+ ENV.gasCounter += amount
32+ }
33+ }
34+
35+ /**
36+ * Returns the current gasCounter
37+ * @return {integer}
38+ */
39+ gasUsed () {
40+ return ENV.gasCounter
41+ }
42+
43+ /**
44+ * Returns the current gasCounter
45+ * @return {integer}
46+ */
47+ gasLeft () {
48+ return ENV.gas - ENV.gasCounter
49+ }
50+
51+ /**
52+ * Gets address of currently executing account and loads it into memory at
53+ * the given offset.
54+ * @param {integer} offset
55+ */
56+ address (offset) {
57+ const address = ENV.address
58+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
59+ memory.set(address)
60+ }
61+
62+ /**
63+ * Gets balance of the given account and loads it into memory at the given
64+ * offset.
65+ * @param {integer} addressOffset the memory offset to laod the address
66+ * @param {integer} resultOffset
67+ */
68+ balance (addressOffset, offset) {
69+ const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
70+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.MAX_BAL_BYTES)
71+ const balance = ENV.getBalance(address)
72+ memory.set(balance)
73+ }
74+
75+ /**
76+ * Gets the execution's origination address and loads it into memory at the
77+ * given offset. This is the sender of original transaction; it is never an
78+ * account with non-empty associated code.
79+ * @param {integer} offset
80+ */
81+ origin (offset) {
82+ const origin = ENV.origin
83+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
84+ memory.set(origin)
85+ }
86+
87+ /**
88+ * Gets caller address and loads it into memory at the given offset. This is
89+ * the address of the account that is directly responsible for this execution.
90+ * @param {integer} offset
91+ */
92+ caller (offset) {
93+ const caller = ENV.caller
94+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
95+ memory.set(caller)
96+ }
97+
98+ /**
99+ * Gets the deposited value by the instruction/transaction responsible for
100+ * this execution and loads it into memory at the given location.
101+ * @param {integer} offset
102+ */
103+ callValue (offset) {
104+ const callValue = ENV.callValue
105+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.MAX_BAL_BYTES)
106+ memory.set(callValue)
107+ }
108+
109+ /**
110+ * Get size of input data in current environment. This pertains to the input
111+ * data passed with the message call instruction or transaction.
112+ * @return {integer}
113+ */
114+ callDataSize () {
115+ return ENV.callData.byteLength
116+ }
117+
118+ /**
119+ * Copys the input data in current environment to memory. This pertains to
120+ * the input data passed with the message call instruction or transaction.
121+ * @param {integer} offset the offset in memory to load into
122+ * @param {integer} dataOffset the offset in the input data
123+ * @param {integer} length the length of data to copy
124+ */
125+ callDataCopy (offset, dataOffset, length) {
126+ const callData = new Uint8Array(ENV.callData, offset, length)
127+ const memory = new Uint8Array(MOD.exports.memory, offset, length)
128+ memory.set(callData)
129+ }
130+
131+ /**
132+ * Gets the size of code running in current environment.
133+ * @return {interger}
134+ */
135+ codeSize () {
136+ return ENV.code.byteLength
137+ }
138+
139+ /**
140+ * Copys the code running in current environment to memory.
141+ * @param {integer} offset the memory offset
142+ * @param {integer} codeOffset the code offset
143+ * @param {integer} length the length of code to copy
144+ */
145+ codeCopy (offset, codeOffset, length) {
146+ const code = new Uint8Array(ENV.code, codeOffset, length)
147+ const memory = new Uint8Array(MOD.exports.memory, offset, length)
148+ memory.set(code)
149+ }
150+
151+ /**
152+ * Get size of an account’s code.
153+ * @param {integer} addressOffset the offset in memory to load the address from
154+ * @return {integer}
155+ */
156+ extCodeSize (addressOffset) {
157+ const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
158+ const code = this.environment.getCode(address)
159+ return code.byteLength
160+ }
161+
162+ /**
163+ * Copys the code of an account to memory.
164+ * @param {integer} addressOffset the memory offset of the address
165+ * @param {integer} offset the memory offset
166+ * @param {integer} codeOffset the code offset
167+ * @param {integer} length the length of code to copy
168+ */
169+ extCodeCopy (addressOffset, offset, codeOffset, length) {
170+ const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
171+ let code = this.environment.getCode(address)
172+ code = new Uint8Array(code, codeOffset, length)
173+ const memory = new Uint8Array(MOD.exports.memory, offset, length)
174+ memory.set(code)
175+ }
176+
177+ /**
178+ * Gets price of gas in current environment.
179+ * @return {integer}
180+ */
181+ gasPrice () {
182+ return ENV.gasPrice
183+ }
184+
185+ /**
186+ * Gets the hash of one of the 256 most recent complete blocks.
187+ * @param {integer} number which block to load
188+ * @param {integer} offset the offset to load the hash into
189+ */
190+ blockHash (number, offset) {
191+ const hash = this.environment.getBlockHash(number)
192+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
193+ memory.set(hash)
194+ }
195+
196+ /**
197+ * Gets the block’s beneficiary address and loads into memory.
198+ * @param offset
199+ */
200+ coinbase (offset) {
201+ const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
202+ memory.set(ENV.coinbase)
203+ }
204+
205+ /**
206+ * Get the block’s timestamp.
207+ * @return {integer}
208+ */
209+ timestamp () {
210+ return ENV.timestamp
211+ }
212+
213+ /**
214+ * Get the block’s number.
215+ * @return {integer}
216+ */
217+ number () {
218+ return ENV.number
219+ }
220+
221+ /**
222+ * Get the block’s difficulty.
223+ * @return {integer}
224+ */
225+ difficulty () {
226+ return ENV.difficulty
227+ }
228+
229+ /**
230+ * Get the block’s gas limit.
231+ * @return {integer}
232+ */
233+ gasLimit () {
234+ return ENV.gasLimit
235+ }
236+
237+ /**
238+ * Creates a new log in the current environment
239+ * @param {integer} dataOffset the offset in memory to load the memory
240+ * @param {integer} length the data length
241+ * TODO: replace with variadic
242+ */
243+ log (dataOffset, length, topic1, topic2, topic3, topic4, topic5) {
244+ const data = new Uint8Array(MOD.exports.memory, dataOffset, length)
245+ ENV.logs.push({
246+ data: data,
247+ topics: [topic1, topic2, topic3, topic4, topic5]
248+ })
249+ }
250+
251+ /**
252+ * Creates a new contract with a given value.
253+ * @param {integer} valueOffset the offset in memory to the value from
254+ * @param {integer} dataOffset the offset to load the code for the new contract from
255+ * @param {integer} length the data length
256+ */
257+ create (valueOffset, dataOffset, length) {
258+ const value = new Uint8Array(MOD.exports.memory, valueOffset, constants.MAX_BAL_BYTES)
259+ const data = new Uint8Array(MOD.exports.memory, dataOffset, length)
260+ const result = ENV.create(value, data)
261+ return result
262+ }
263+
264+ /**
265+ * Sends a message with arbiatary date to a given address path
266+ * @param {integer} addressOffset the offset to load the address path from
267+ * @param {integer} valueOffset the offset to load the value from
268+ * @param {integer} dataOffset the offset to load data from
269+ * @param {integer} dataLength the length of data
270+ * @param {integer} resultOffset the offset to store the result data at
271+ * @param {integer} resultLength
272+ * @param {integer} gas
273+ * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
274+ * TODO: add proper gas counting
275+ */
276+ call (addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, gas) {
277+ if (gas === undefined) {
278+ gas = this.gasLeft()
279+ }
280+ // Load the params from mem
281+ const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
282+ const value = new Uint8Array(MOD.exports.memory, valueOffset, constants.MAX_BAL_BYTES)
283+ const data = new Uint8Array(MOD.exports.memory, dataOffset, dataLength)
284+ // Run the call
285+ const [result, errorCode] = ENV.call(gas, address, value, data)
286+ const memory = new Uint8Array(MOD.exports.memory, resultOffset, resultLength)
287+ memory.set(result)
288+
289+ return errorCode
290+ }
291+
292+ /**
293+ * Message-call into this account with an alternative account’s code, but
294+ * persisting the current values for sender and value.
295+ * @param {integer} gas
296+ * @param {integer} addressOffset the offset to load the address path from
297+ * @param {integer} valueOffset the offset to load the value from
298+ * @param {integer} dataOffset the offset to load data from
299+ * @param {integer} dataLength the length of data
300+ * @param {integer} resultOffset the offset to store the result data at
301+ * @param {integer} resultLength
302+ * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
303+ */
304+ callDelegate (gas, addressOffset, dataOffset, dataLength, resultOffset, resultLength) {
305+ const data = new Uint8Array(this.module.memory, dataOffset, dataLength)
306+ const address = new Uint8Array(this.module.memory, addressOffset, constants.ADD_SIZE_BYTES)
307+ const [result, errorCode] = this.environment.callDelegate(gas, address, data)
308+ const memory = new Uint8Array(this.module.memory, resultOffset, resultLength)
309+ memory.set(result)
310+
311+ return errorCode
312+ }
313+
314+ /**
315+ * store a value at a given path in long term storage which are both loaded
316+ * from Memory
317+ * @param {interger} pathOffest the memory offset to load the the path from
318+ * @param {interger} valueOffset the memory offset to load the value from
319+ */
320+ sstore (pathOffest, valueOffset) {
321+ const path = new Uint8Array(this.module.memory, pathOffest, pathOffest + 32)
322+ const value = new Uint8Array(this.module.memory, valueOffset, valueOffset + 32)
323+ this.environment.state.set(path, value)
324+ }
325+
326+ /**
327+ * reterives a value at a given path in long term storage
328+ * @param {interger} pathOffest the memory offset to load the the path from
329+ * @param {interger} resultOffset the memory offset to load the value from
330+ */
331+ sget (pathOffest, resultOffset) {
332+ const path = new Uint8Array(this.module.memory, pathOffest, pathOffest + 32)
333+ const result = this.environment.state.get(path)
334+ const memory = new Uint8Array(this.module.memory, resultOffset, resultOffset + 32)
335+ memory.set(result)
336+ }
337+
338+ /**
339+ * Halt execution returning output data.
340+ * @param {integer} offset the offset of the output data.
341+ * @param {integer} length the length of the output data.
342+ */
343+ return (offset, length) {
344+ this.environment.returnValue = new Uint8Array(this.module.memory, offset, length)
345+ }
346+
347+ /**
348+ * Halt execution and register account for later deletion giving the remaining
349+ * balance to an address path
350+ * @param {integer} offset the offset to load the address from
351+ */
352+ suicide (addressOffset) {
353+ const address = new Uint8Array(this.module.memory, addressOffset, constants.ADD_SIZE_BYTES)
354+ this.environment.suicideAddress = address
355+ }
356+}
package.jsonView
@@ -1,0 +1,14 @@
1+{
2+ "name": "js-prototype",
3+ "version": "0.0.0",
4+ "description": "",
5+ "scripts": {
6+ "test": "tape ./test_runner.js"
7+ },
8+ "author": "mjbecze <mjbecze@gmail.com>",
9+ "license": "ISC",
10+ "dependencies": {
11+ "es6-autobind": "^1.0.2",
12+ "tape": "^4.5.1"
13+ }
14+}

Built with git-ssb-web