git ssb

0+

wanderer🌟 / js-primea-hypervisor



Commit 7ff034895b684011d11e02744533ab8d7987b4e8

sstore/ssload working

wanderer committed on 10/30/2016, 5:41:14 PM
Parent: 69097f452f01a61429f16530219f9f1dc548b8d3

Files changed

environment.jschanged
index.jschanged
interface.jschanged
package.jsonchanged
environment.jsView
@@ -1,11 +1,13 @@
1+const Vertex = require('merkle-trie')
2+const Store = require('merkle-trie/store')
13 const U256 = require('./deps/u256.js')
24 const Address = require('./deps/address.js')
35 const Block = require('./deps/block.js')
46 const fakeBlockChain = require('./fakeBlockChain.js')
57
68 module.exports = class Environment {
7- constructor (data) {
9+ constructor (data = {}) {
810 const defaults = {
911 block: new Block(),
1012 blockchain: fakeBlockChain,
1113 // gas tank
@@ -24,54 +26,54 @@
2426 logs: [],
2527 selfDestruct: false,
2628 selfDestructAddress: new Address('0x0000000000000000000000000000000000000000'),
2729 // more output calls
28- returnValue: new Uint8Array()
30+ returnValue: new Uint8Array(),
31+ state: new Vertex({store: new Store()})
2932 }
3033
31- this.state = new Map()
32-
33- Object.assign(this, defaults, data || {})
34+ Object.assign(this, defaults, data)
3435 }
3536
36- addAccount (address, trie) {
37- let account = new Map()
38- account.set('nonce', trie.nonce || new U256(0))
39- account.set('balance', trie.balance || new U256(0))
40- account.set('code', trie.code || new Uint8Array())
41- account.set('storage', trie.storage || new Map())
42- this.state.set(address.toString(), account)
43- }
37+ // addAccount (address, trie) {
38+ // let account = new Vertex()
39+ // account.set('nonce', trie.nonce || new U256(0))
40+ // account.set('balance', trie.balance || new U256(0))
41+ // account.set('code', trie.code || new Uint8Array())
42+ // account.set('storage', trie.storage || new Map())
43+ // this.state.set(address.toString(), account)
44+ // }
4445
4546 isAccountPresent (address) {
46- const account = this.state.get(address.toString())
47- if (account) {
48- return true
49- } else {
50- return false
51- }
47+ // const account = this.state.get(address.toString())
48+ // if (account) {
49+ // return true
50+ // } else {
51+ // return false
52+ // }
5253 }
5354
5455 getBalance (address) {
55- const account = this.state.get(address.toString())
56- if (account) {
57- return account.get('balance')
58- } else {
59- return new U256()
60- }
56+ // const account = this.state.get(address.toString())
57+ // if (account) {
58+ // return account.get('balance')
59+ // } else {
60+ // return new U256()
61+ // }
6162 }
6263
6364 getCode (address) {
64- const account = this.state.get(address.toString())
65- if (account) {
66- return account.get('code')
67- } else {
68- return Uint8Array.from(new Buffer([]))
69- }
65+ // const account = this.state.get(address.toString())
66+ // if (account) {
67+ // return account.get('code')
68+ // } else {
69+ // return Uint8Array.from(new Buffer([]))
70+ // }
7071 }
7172
7273 getBlockHash (height) {
73- return this.blockchain.getBlock(height).hash()
74+ // return this.blockchain.getBlock(height).hash()
75+ return this.root.getBlockAt(height).then(block => block.hash())
7476 }
7577
7678 set createHandler (value) {
7779 this.createhandler = value
@@ -88,9 +90,9 @@
8890 }
8991
9092 call (gas, address, value, data) {
9193 // FIXME: create a child environment here
92- const ret = this.callhandler({
94+ const ret = this.root.messagehandler({
9395 from: this.address,
9496 to: address,
9597 gasLimit: gas,
9698 value: value,
index.jsView
@@ -32,18 +32,21 @@
3232 module.exports = class Kernel {
3333 // runs some code in the VM
3434 constructor (environment = new Environment()) {
3535 this.environment = environment
36+ this._runningOps = Promise.resolve()
3637
37- this.environment.addAccount(identityContract, {})
38- this.environment.addAccount(meteringContract, {})
39- this.environment.addAccount(transcompilerContract, {})
38+ // this.environment.addAccount(identityContract, {})
39+ // this.environment.addAccount(meteringContract, {})
40+ // this.environment.addAccount(transcompilerContract, {})
4041 }
4142
4243 // handles running code.
4344 // NOTE: it assumes that wasm will raise an exception if something went wrong,
4445 // otherwise execution succeeded
45- codeHandler (code, ethInterface = new Interface(new Environment())) {
46+ codeHandler (code, ethInterface = new Interface(new Environment(), this)) {
47+ // TODO remove
48+ ethInterface.kernel = this
4649 const debugInterface = new DebugInterface(ethInterface.environment)
4750 const module = WebAssembly.Module(code)
4851 const imports = {
4952 'ethereum': ethInterface.exportTable,
@@ -61,24 +64,33 @@
6164 imports.ethereum.useGas = ethInterface.shims.exports.useGas
6265 imports.ethereum.getGasLeft = ethInterface.shims.exports.getGasLeft
6366 imports.ethereum.call = ethInterface.shims.exports.call
6467
65- const instance = WebAssembly.Instance(module, imports)
68+ const instance = this.instance = WebAssembly.Instance(module, imports)
6669
6770 ethInterface.setModule(instance)
6871 debugInterface.setModule(instance)
6972
7073 if (instance.exports.main) {
7174 instance.exports.main()
7275 }
73- return instance
76+ return this.onDone()
7477 }
7578
79+ // returns a promise that resolves when the wasm instance is done running
80+ async onDone () {
81+ let prevOps
82+ while (prevOps !== this._runningOps) {
83+ prevOps = this._runningOps
84+ await this._runningOps
85+ }
86+ }
87+
7688 // loads code from the merkle trie and delegates the message
7789 // Detects if code is EVM or WASM
7890 // Detects if the code injection is needed
7991 // Detects if transcompilation is needed
80- callHandler (call) {
92+ messageHandler (call) {
8193 // FIXME: this is here until these two contracts are compiled to WASM
8294 // The two special contracts (precompiles now, but will be real ones later)
8395 if (call.to.equals(meteringContract)) {
8496 return Precompile.meteringInjector(call)
interface.jsView
@@ -12,9 +12,10 @@
1212 const U256_SIZE_BYTES = 32
1313
1414 // The interface exposed to the WebAessembly Core
1515 module.exports = class Interface {
16- constructor (environment) {
16+ constructor (environment, kernel) {
17+ this.kernel = kernel
1718 this.environment = environment
1819 const shimBin = fs.readFileSync(path.join(__dirname, '/wasm/interface.wasm'))
1920 const shimMod = WebAssembly.Module(shimBin)
2021 this.shims = WebAssembly.Instance(shimMod, {
@@ -403,9 +404,8 @@
403404 * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
404405 */
405406 _call (gasHigh, gasLow, addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength) {
406407 const gas = from64bit(gasHigh, gasLow)
407- console.log(gas);
408408 // Load the params from mem
409409 const address = Address.fromMemory(this.getMemory(addressOffset, ADDRESS_SIZE_BYTES))
410410 const value = U256.fromMemory(this.getMemory(valueOffset, U128_SIZE_BYTES))
411411
@@ -499,53 +499,66 @@
499499 * @param {interger} pathOffest the memory offset to load the the path from
500500 * @param {interger} valueOffset the memory offset to load the value from
501501 */
502502 storageStore (pathOffset, valueOffset, cbDest) {
503- console.log('sstore');
504- const path = new Buffer(this.getMemory(pathOffset, U256_SIZE_BYTES)).toString('hex')
503+ this.takeGas(5000)
504+ const path = [...this.getMemory(pathOffset, U256_SIZE_BYTES)]
505505 // copy the value
506506 const value = this.getMemory(valueOffset, U256_SIZE_BYTES).slice(0)
507- console.log('value:' + value)
508- console.log('path:' + path)
509- const oldValue = this.environment.state.get(path)
510507 const valIsZero = value.every((i) => i === 0)
508+ const opPromise = this.environment.state.get(path)
509+ .catch(() => {
510+ // TODO: handle errors
511+ // the value was not found
512+ return null
513+ })
511514
512- this.takeGas(5000)
515+ // wait for all the prevouse async ops to finish before running the callback
516+ this.kernel._runningOps = Promise.all([this.kernel._runningOps, opPromise])
517+ .then(values => {
518+ const oldValue = values.pop()
519+ if (valIsZero && oldValue) {
520+ // delete a value
521+ this.environment.gasRefund += 15000
522+ this.environment.state.del(path)
523+ } else {
524+ if (!valIsZero && !oldValue) {
525+ // creating a new value
526+ this.takeGas(15000)
527+ }
528+ // update
529+ this.environment.state.set(path, value)
530+ }
513531
514- // write
515- if (!valIsZero && !oldValue) {
516- this.takeGas(15000)
517- }
518-
519- // delete
520- if (valIsZero && oldValue) {
521- this.environment.gasRefund += 15000
522- this.environment.state.delete(path)
523- } else {
524- this.environment.state.set(path, value)
525- }
526-
527- setTimeout(() => {
528- this.module.exports['0']()
529- }, 0)
532+ this.module.exports[cbDest.toString()]()
533+ })
530534 }
531535
532536 /**
533537 * reterives a value at a given path in long term storage
534538 * @param {interger} pathOffest the memory offset to load the the path from
535539 * @param {interger} resultOffset the memory offset to load the value from
536540 */
537541 storageLoad (pathOffset, resultOffset, cbDest) {
538- console.log('sload');
539542 this.takeGas(50)
540543
541- const path = new Buffer(this.getMemory(pathOffset, U256_SIZE_BYTES)).toString('hex')
542- console.log(path);
543- const result = this.environment.state.get(path) || new Uint8Array(32)
544- this.setMemory(resultOffset, U256_SIZE_BYTES, result)
545- setTimeout(() => {
546- this.module.exports['0']()
547- }, 0)
544+ // convert the path to an array
545+ const path = [...this.getMemory(pathOffset, U256_SIZE_BYTES)]
546+ const opPromise = this.environment.state.get(path)
547+ .catch(() => {
548+ // TODO: handle other possible errors
549+ // if the value was not found return a empty array
550+ return new Uint8Array(32)
551+ })
552+
553+ // wait for all the prevouse async ops to finish before running the callback
554+ this.kernel._runningOps = Promise
555+ .all([this.kernel._runningOps, opPromise])
556+ .then(values => {
557+ const result = values.pop()
558+ this.setMemory(resultOffset, U256_SIZE_BYTES, result)
559+ this.module.exports[cbDest.toString()]()
560+ })
548561 }
549562
550563 /**
551564 * Halt execution returning output data.
package.jsonView
@@ -38,7 +38,8 @@
3838 "dependencies": {
3939 "bn.js": "^4.11.6",
4040 "ethereumjs-block": "^1.2.2",
4141 "ethereumjs-tx": "^1.1.2",
42- "ethereumjs-util": "^4.5.0"
42+ "ethereumjs-util": "^4.5.0",
43+ "merkle-trie": "0.0.0"
4344 }
4445 }

Built with git-ssb-web