Commit 76b626ab5a6d24e48ccefffb8900dc9052b0b36d
restuctured
wanderer committed on 7/22/2016, 2:41:41 AMParent: 9277afcb2a63e13cddbed76dbfa1c1cc85f210d2
Files changed
environment.js | changed |
index.js | changed |
interface.js | changed |
tests/interfaceRunner.js | changed |
environment.js | ||
---|---|---|
@@ -6,8 +6,9 @@ | ||
6 | 6 | const defaults = { |
7 | 7 | // gas tank |
8 | 8 | gasPrice: 0, |
9 | 9 | gasLimit: 0, // The gas limit for the block |
10 | + gasRefund: 0, | |
10 | 11 | // call infromation |
11 | 12 | address: new Uint8Array(20), |
12 | 13 | origin: new Uint8Array(20), |
13 | 14 | coinbase: new Uint8Array(20), |
@@ -23,18 +24,17 @@ | ||
23 | 24 | // more output calls |
24 | 25 | returnValue: new ArrayBuffer() |
25 | 26 | } |
26 | 27 | |
27 | - this.state = new Graph() | |
28 | + this.state = new Map() | |
28 | 29 | |
29 | 30 | if (data) { |
30 | 31 | data = JSON.parse(data) |
31 | 32 | } else { |
32 | 33 | data = {} |
33 | 34 | } |
34 | 35 | |
35 | 36 | Object.assign(this, defaults, data) |
36 | - | |
37 | 37 | if (data.accounts) { |
38 | 38 | this.accounts = new Graph() |
39 | 39 | const self = this |
40 | 40 | data.accounts.forEach((account) => { |
@@ -73,23 +73,8 @@ | ||
73 | 73 | |
74 | 74 | getBlockHash (height) { |
75 | 75 | // STUB |
76 | 76 | } |
77 | - | |
78 | - // kernal | |
79 | - create (code, value) { | |
80 | - // STUB | |
81 | - } | |
82 | - | |
83 | - call (gas, address, value, data) { | |
84 | - // STUB | |
85 | - return // result | |
86 | - } | |
87 | - | |
88 | - delegateCall (gas, address, data) { | |
89 | - // STUB | |
90 | - return // result | |
91 | - } | |
92 | 77 | } |
93 | 78 | |
94 | 79 | function hexStr2arrayBuf (string) { |
95 | 80 | const ab = new ArrayBuffer(string.length / 2) |
index.js | ||
---|---|---|
@@ -1,27 +1,32 @@ | ||
1 | 1 | /** |
2 | 2 | * This implements the Ethereum Kernel |
3 | - * The kernal handles the following | |
3 | + * The Kernel Contract handles the following | |
4 | 4 | * - Interprocess communications |
5 | 5 | * - Intializing the VM and exposes ROM to it (codeHandler) |
6 | 6 | * - Expose namespace which VM instance exists and Intializes the Environment (callHandler) |
7 | 7 | * - Provides some built in contract (runTx, runBlock) |
8 | 8 | * - Provides resource sharing and limiting via gas |
9 | 9 | * |
10 | 10 | * All State should be stored in the Environment. |
11 | + * | |
11 | 12 | */ |
12 | 13 | // const Environment = require('./environment.js') |
14 | +// | |
15 | +// The Kernel Exposes this Interface to VM instances it makes | |
13 | 16 | const Interface = require('./interface.js') |
17 | +// The Kernel Stores all of its state in the Environment. The Interface is used | |
18 | +// to by the VM to retrive infromation from the Environment. | |
14 | 19 | const Environment = require('./environment.js') |
15 | 20 | |
16 | 21 | module.exports = class Kernal { |
17 | 22 | // runs some code in the VM |
18 | - constructor (nameState) { | |
19 | - this.state = nameState | |
23 | + constructor (environment = new Environment()) { | |
24 | + this.environment = environment | |
20 | 25 | } |
21 | 26 | |
22 | 27 | // handles running code. |
23 | - static codeHandler (code, ethInterface = new Interface()) { | |
28 | + static codeHandler (code, ethInterface) { | |
24 | 29 | const instance = Wasm.instantiateModule(code, { |
25 | 30 | 'ethereum': ethInterface |
26 | 31 | }) |
27 | 32 | |
@@ -35,10 +40,14 @@ | ||
35 | 40 | // loads code from the merkle trie and delegates the message |
36 | 41 | // Detects if code is EVM or WASM |
37 | 42 | // Detects if the code injection is needed |
38 | 43 | // Detects if transcompilation is needed |
39 | - static callHandler (path, data, environment = new Environment()) { | |
40 | - // return instance | |
44 | + static callHandler (path, data) { | |
45 | + // creats a new Kernal | |
46 | + // const environment = new Environment(data) | |
47 | + // environment.parent = this | |
48 | + // const kernel = new Kernel(this, environment) | |
49 | + // kernel.codeHandler(code) | |
41 | 50 | } |
42 | 51 | |
43 | 52 | // run tx; the tx message handler |
44 | 53 | runTx (tx, environment = new Environment()) { |
interface.js | ||
---|---|---|
@@ -3,13 +3,15 @@ | ||
3 | 3 | * enables to interact with the Ethereum Environment |
4 | 4 | */ |
5 | 5 | const Environment = require('./environment.js') |
6 | 6 | const constants = require('./constants.js') |
7 | +// const Graph = require('generic-digraph') | |
7 | 8 | |
8 | 9 | // function.bind is not working corretly whith Wasm imports. So instead create |
9 | 10 | // a global for now. TODO REMOVE |
10 | 11 | let ENV |
11 | 12 | let MOD |
13 | +let self | |
12 | 14 | // The interface exposed to the WebAessembly Core |
13 | 15 | module.exports = class Interface { |
14 | 16 | |
15 | 17 | debugPrint (a) { |
@@ -19,10 +21,11 @@ | ||
19 | 21 | memPrint () { |
20 | 22 | console.log((new Uint8Array(MOD.exports.memory)).toString()) |
21 | 23 | } |
22 | 24 | |
23 | - constructor (environment = new Environment()) { | |
24 | - ENV = this.environment = environment | |
25 | + constructor (kernal) { | |
26 | + ENV = this.environment = kernal.environment | |
27 | + self = this | |
25 | 28 | } |
26 | 29 | |
27 | 30 | setModule (mod) { |
28 | 31 | this.module = MOD = mod |
@@ -315,21 +318,35 @@ | ||
315 | 318 | * @param {interger} pathOffest the memory offset to load the the path from |
316 | 319 | * @param {interger} valueOffset the memory offset to load the value from |
317 | 320 | */ |
318 | 321 | sstore (pathOffest, valueOffset) { |
319 | - const path = new Uint8Array(MOD.exports.memory, pathOffest, 32) | |
320 | - const value = new Uint8Array(MOD.exports.memory, valueOffset, 32) | |
321 | - ENV.state.set(path, value) | |
322 | + const path = new Uint8Array(MOD.exports.memory, pathOffest, 32).join('') | |
323 | + const value = new Uint8Array(MOD.exports.memory, valueOffset, 32) | |
324 | + const oldValue = ENV.state.get(path) | |
325 | + const valIsZero = value.every((i) => i === 0) | |
326 | + | |
327 | + // write | |
328 | + if (!valIsZero && !oldValue) { | |
329 | + ENV.gasLimit -= 15000 | |
330 | + } | |
331 | + | |
332 | + // delete | |
333 | + if (valIsZero && oldValue) { | |
334 | + ENV.gasRefund += 15000 | |
335 | + ENV.state.delete(path) | |
336 | + } else { | |
337 | + ENV.state.set(path, value) | |
338 | + } | |
322 | 339 | } |
323 | 340 | |
324 | 341 | /** |
325 | 342 | * reterives a value at a given path in long term storage |
326 | 343 | * @param {interger} pathOffest the memory offset to load the the path from |
327 | 344 | * @param {interger} resultOffset the memory offset to load the value from |
328 | 345 | */ |
329 | 346 | sload (pathOffest, resultOffset) { |
330 | - const path = new Uint8Array(MOD.exports.memory, pathOffest, 32) | |
331 | - const result = ENV.state.getValue(path) | |
347 | + const path = new Uint8Array(MOD.exports.memory, pathOffest, 32).join('') | |
348 | + const result = ENV.state.get(path) | |
332 | 349 | const memory = new Uint8Array(MOD.exports.memory, resultOffset, 32) |
333 | 350 | memory.set(result) |
334 | 351 | } |
335 | 352 |
tests/interfaceRunner.js | ||
---|---|---|
@@ -2,8 +2,9 @@ | ||
2 | 2 | const tape = require('tape') |
3 | 3 | const fs = require('fs') |
4 | 4 | const cp = require('child_process') |
5 | 5 | |
6 | +const Kernel = require('../index.js') | |
6 | 7 | const Environment = require('../environment.js') |
7 | 8 | const Interface = require('../interface.js') |
8 | 9 | const dir = __dirname + '/interface' |
9 | 10 | // get the test names |
@@ -18,9 +19,10 @@ | ||
18 | 19 | const buffer = fs.readFileSync(`${dir}/${testName}.wasm`) |
19 | 20 | const envData = fs.readFileSync(`${dir}/${testName}.json`) |
20 | 21 | |
21 | 22 | const environment = new Environment(envData) |
22 | - const ethInterface = new Interface(environment) | |
23 | + const kernel = new Kernel(environment) | |
24 | + const ethInterface = new Interface(kernel) | |
23 | 25 | |
24 | 26 | try { |
25 | 27 | const mod = Wasm.instantiateModule(buffer, {'ethereum': ethInterface}) |
26 | 28 | ethInterface.setModule(mod) |
Built with git-ssb-web