Commit f8c9ead18a27b0962868bf70b4fa256cb3fb1606
added sstore test
wanderer committed on 7/14/2016, 10:03:05 PMParent: 2c04524fc8e9b757c060e0e2cf80d26d6d411e57
Files changed
README.md | changed |
environment.js | changed |
index.js | changed |
interface.js | changed |
package.json | changed |
tests/sstore.json | added |
tests/sstore.wast | added |
debugInterface.js | added |
README.md | ||
---|---|---|
@@ -1,14 +1,13 @@ | ||
1 | 1 | # SYNOPSIS - WIP |
2 | 2 | [![Gitter](https://img.shields.io/gitter/room/ethereum/ethereumjs-lib.svg?style=flat-square)](https://gitter.im/ethereum/ethereumjs-lib) or #ethereumjs on freenode |
3 | - | |
4 | 3 | [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) |
5 | 4 | |
6 | 5 | This is a JS prototype of the [eWASM kernal](https://github.com/ethereum/evm2.0-design). |
7 | 6 | |
8 | 7 | |
9 | 8 | # INSTALL |
10 | -You need to compile [nodejs](https://github.com/nodejs/node) from master to run | |
9 | +You need to compile [nodejs](https://github.com/nodejs/node) from master to run | |
11 | 10 | ~~`npm install ewasm-kernal`~~ |
12 | 11 | |
13 | 12 | clone and run `npm install` |
14 | 13 |
environment.js | ||
---|---|---|
@@ -3,26 +3,32 @@ | ||
3 | 3 | |
4 | 4 | module.exports = class Environment { |
5 | 5 | constructor (data) { |
6 | 6 | const defaults = { |
7 | + // gas tank | |
7 | 8 | gasCounter: 0, // TODO: gasCounter is only 53 bits |
8 | 9 | gas: 0, // The amount of gas this contract has |
9 | 10 | gasPrice: 0, |
10 | 11 | gasLimit: 0, // The gas limit for the block |
12 | + // call infromation | |
11 | 13 | address: new Uint8Array(20), |
12 | 14 | origin: new Uint8Array(20), |
13 | 15 | coinbase: new Uint8Array(20), |
14 | 16 | difficulty: new Uint8Array(20), |
15 | 17 | caller: new Uint8Array(20), |
16 | 18 | callValue: new Uint8Array(MAX_BAL_BYTES), |
17 | 19 | callData: new ArrayBuffer(), |
20 | + // the ROM | |
18 | 21 | code: new ArrayBuffer(), // the current running code |
22 | + // output calls | |
19 | 23 | logs: [], |
20 | - returnValue: new ArrayBuffer(), | |
21 | 24 | suicideAddress: new ArrayBuffer(), |
22 | - accounts: new Map() | |
25 | + // more output calls | |
26 | + returnValue: new ArrayBuffer() | |
23 | 27 | } |
24 | 28 | |
29 | + this.state = new Graph() | |
30 | + | |
25 | 31 | if (data) { |
26 | 32 | data = JSON.parse(data) |
27 | 33 | Object.assign(this, defaults, data) |
28 | 34 | } else { |
@@ -31,9 +37,8 @@ | ||
31 | 37 | |
32 | 38 | if (data.accounts) { |
33 | 39 | this.accounts = new Graph() |
34 | 40 | const self = this |
35 | - debugger | |
36 | 41 | data.accounts.forEach((account) => { |
37 | 42 | self.accounts.set(new Uint8Array(account[0]).toString(), account[1]) |
38 | 43 | }) |
39 | 44 | } |
index.js | ||
---|---|---|
@@ -10,27 +10,33 @@ | ||
10 | 10 | * All State should be stored in the Environment. |
11 | 11 | */ |
12 | 12 | // const Environment = require('./environment.js') |
13 | 13 | const Interface = require('./interface.js') |
14 | +const Environment = require('./environment.js') | |
14 | 15 | |
15 | 16 | module.exports = class Kernal { |
16 | 17 | // runs some code in the VM |
17 | 18 | constructor (nameState) { |
18 | 19 | this.state = nameState |
19 | 20 | } |
20 | 21 | |
21 | 22 | // handles running code. |
22 | - static codeHandler (code, environment) { | |
23 | + static codeHandler (code, environment = new Environment()) { | |
23 | 24 | const ethInterface = new Interface(environment) |
24 | 25 | const instance = Wasm.instantiateModule(code, { |
25 | 26 | 'ethereum': ethInterface |
26 | 27 | }) |
27 | - ethInterface.setModule(ethInterface) | |
28 | + ethInterface.setModule(instance) | |
29 | + if (instance.exports.main) { | |
30 | + instance.exports.main() | |
31 | + } | |
28 | 32 | return instance |
29 | 33 | } |
30 | 34 | |
31 | 35 | // loads code from the merkle trie and delegates the message |
36 | + // Detects if code is EVM or WASM | |
32 | 37 | // Detects if the code injection is needed |
38 | + // Detects if transcompilation is needed | |
33 | 39 | static callHandler (path, data, environment) { |
34 | 40 | // const instance = Wasm.instantiateModule(code, interface) |
35 | 41 | // interface.setModule(instance) |
36 | 42 | // return instance |
@@ -47,9 +53,8 @@ | ||
47 | 53 | // verify block then run each tx |
48 | 54 | block.tx.forEach((tx) => { |
49 | 55 | this.runTx(tx, environment) |
50 | 56 | }) |
51 | - | |
52 | 57 | } |
53 | 58 | |
54 | 59 | // run blockchain |
55 | 60 | // runBlockchain () {} |
interface.js | ||
---|---|---|
@@ -9,24 +9,25 @@ | ||
9 | 9 | let ENV |
10 | 10 | let MOD |
11 | 11 | // The interface exposed to the WebAessembly Core |
12 | 12 | module.exports = class Interface { |
13 | + | |
14 | + debugPrint (a) { | |
15 | + console.log(a) | |
16 | + } | |
17 | + | |
18 | + memPrint () { | |
19 | + console.log((new Uint8Array(MOD.exports.memory)).toString()) | |
20 | + } | |
21 | + | |
13 | 22 | constructor (environment) { |
14 | 23 | ENV = this.environment = environment |
15 | 24 | } |
16 | 25 | |
17 | 26 | setModule (mod) { |
18 | 27 | this.module = MOD = mod |
19 | 28 | } |
20 | 29 | |
21 | - // debugPrint (a, b) { | |
22 | - // console.log(a) | |
23 | - // } | |
24 | - | |
25 | - // memPrint () { | |
26 | - // console.log((new Uint8Array(MOD.exports.memory)).toString()) | |
27 | - // } | |
28 | - | |
29 | 30 | /** |
30 | 31 | * Subtracts an amount to the gas counter |
31 | 32 | * @param {integer} amount the amount to subtract to the gas counter |
32 | 33 | */ |
@@ -265,9 +266,9 @@ | ||
265 | 266 | return result |
266 | 267 | } |
267 | 268 | |
268 | 269 | /** |
269 | - * Sends a message with arbiatary date to a given address path | |
270 | + * Sends a message with arbiatary data to a given address path | |
270 | 271 | * @param {integer} addressOffset the offset to load the address path from |
271 | 272 | * @param {integer} valueOffset the offset to load the value from |
272 | 273 | * @param {integer} dataOffset the offset to load data from |
273 | 274 | * @param {integer} dataLength the length of data |
@@ -305,12 +306,12 @@ | ||
305 | 306 | * @param {integer} resultLength |
306 | 307 | * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not |
307 | 308 | */ |
308 | 309 | callDelegate (gas, addressOffset, dataOffset, dataLength, resultOffset, resultLength) { |
309 | - const data = new Uint8Array(this.module.memory, dataOffset, dataLength) | |
310 | - const address = new Uint8Array(this.module.memory, addressOffset, constants.ADD_SIZE_BYTES) | |
310 | + const data = new Uint8Array(MOD.exports.memory, dataOffset, dataLength) | |
311 | + const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES) | |
311 | 312 | const [result, errorCode] = this.environment.callDelegate(gas, address, data) |
312 | - const memory = new Uint8Array(this.module.memory, resultOffset, resultLength) | |
313 | + const memory = new Uint8Array(MOD.exports.memory, resultOffset, resultLength) | |
313 | 314 | memory.set(result) |
314 | 315 | |
315 | 316 | return errorCode |
316 | 317 | } |
@@ -321,22 +322,22 @@ | ||
321 | 322 | * @param {interger} pathOffest the memory offset to load the the path from |
322 | 323 | * @param {interger} valueOffset the memory offset to load the value from |
323 | 324 | */ |
324 | 325 | sstore (pathOffest, valueOffset) { |
325 | - const path = new Uint8Array(this.module.memory, pathOffest, pathOffest + 32) | |
326 | - const value = new Uint8Array(this.module.memory, valueOffset, valueOffset + 32) | |
327 | - this.environment.state.set(path, value) | |
326 | + const path = new Uint8Array(MOD.exports.memory, pathOffest, pathOffest + 32) | |
327 | + const value = new Uint8Array(MOD.exports.memory, valueOffset, valueOffset + 32) | |
328 | + ENV.state.set(path, value) | |
328 | 329 | } |
329 | 330 | |
330 | 331 | /** |
331 | 332 | * reterives a value at a given path in long term storage |
332 | 333 | * @param {interger} pathOffest the memory offset to load the the path from |
333 | 334 | * @param {interger} resultOffset the memory offset to load the value from |
334 | 335 | */ |
335 | 336 | sget (pathOffest, resultOffset) { |
336 | - const path = new Uint8Array(this.module.memory, pathOffest, pathOffest + 32) | |
337 | - const result = this.environment.state.get(path) | |
338 | - const memory = new Uint8Array(this.module.memory, resultOffset, resultOffset + 32) | |
337 | + const path = new Uint8Array(MOD.exports.memory, pathOffest, pathOffest + 32) | |
338 | + const result = ENV.state.getValue(path) | |
339 | + const memory = new Uint8Array(MOD.exports.memory, resultOffset, resultOffset + 32) | |
339 | 340 | memory.set(result) |
340 | 341 | } |
341 | 342 | |
342 | 343 | /** |
@@ -344,17 +345,17 @@ | ||
344 | 345 | * @param {integer} offset the offset of the output data. |
345 | 346 | * @param {integer} length the length of the output data. |
346 | 347 | */ |
347 | 348 | return (offset, length) { |
348 | - this.environment.returnValue = new Uint8Array(this.module.memory, offset, length) | |
349 | + this.environment.returnValue = new Uint8Array(MOD.exports.memory, offset, length) | |
349 | 350 | } |
350 | 351 | |
351 | 352 | /** |
352 | 353 | * Halt execution and register account for later deletion giving the remaining |
353 | 354 | * balance to an address path |
354 | 355 | * @param {integer} offset the offset to load the address from |
355 | 356 | */ |
356 | 357 | suicide (addressOffset) { |
357 | - const address = new Uint8Array(this.module.memory, addressOffset, constants.ADD_SIZE_BYTES) | |
358 | + const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES) | |
358 | 359 | this.environment.suicideAddress = address |
359 | 360 | } |
360 | 361 | } |
package.json | ||
---|---|---|
@@ -33,7 +33,7 @@ | ||
33 | 33 | "Wasm" |
34 | 34 | ] |
35 | 35 | }, |
36 | 36 | "dependencies": { |
37 | - "generic-digraph": "^3.1.0" | |
37 | + "generic-digraph": "^3.1.1" | |
38 | 38 | } |
39 | 39 | } |
tests/sstore.wast | ||
---|---|---|
@@ -1,0 +1,24 @@ | ||
1 | +;; starts with an caller of 5d48c1018904a172886829bbbd9c6f4a2d06c47b | |
2 | +(module | |
3 | + (memory 1) | |
4 | + (import $sstore "ethereum" "sstore" (param i32 i32)) | |
5 | + (import $sget "ethereum" "sget" (param i32 i32)) | |
6 | + | |
7 | + (export "test" 0) | |
8 | + (export "a" memory) | |
9 | + (func | |
10 | + (local $temp i64) | |
11 | + (block | |
12 | + ;; should roundtrip store and load a value from storage | |
13 | + (i64.store (i32.const 0) (i64.const 173553719826446289)) | |
14 | + (call_import $sstore (i32.const 64) (i32.const 0)) | |
15 | + (call_import $sget (i32.const 64) (i32.const 64)) | |
16 | + (set_local $temp | |
17 | + (i64.load (i32.const 64))) | |
18 | + | |
19 | + (if (i64.eq (i64.load (i32.const 0)) (i64.const 173553719826446289)) | |
20 | + (return)) | |
21 | + (unreachable) | |
22 | + ) | |
23 | + ) | |
24 | +) |
debugInterface.js | ||
---|---|---|
@@ -1,0 +1,16 @@ | ||
1 | +/** | |
2 | + * Debug Interface | |
3 | + * This expose some functions that can help with debugging wast | |
4 | + */ | |
5 | +const Interface = require('./interface.js') | |
6 | +let MOD | |
7 | + | |
8 | +module.exports = class DebugInterface extends Interface { | |
9 | + debugPrint (a, b) { | |
10 | + console.log(a) | |
11 | + } | |
12 | + | |
13 | + memPrint () { | |
14 | + console.log((new Uint8Array(MOD.exports.memory)).toString()) | |
15 | + } | |
16 | +} |
Built with git-ssb-web