git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 6d71f9bda86609025af68d2581863e0ecb6685f6

Files: 6d71f9bda86609025af68d2581863e0ecb6685f6 / index.js

4970 bytesRaw
1/**
2 * This implements the Ethereum Kernel
3 * Kernels must implement two methods `codeHandler` and `callHandler` (and `linkHandler` for sharding)
4 * The Kernel Contract handles the following
5 * - Interprocess communications
6 * - Intializing the VM and exposes ROM to it (codeHandler)
7 * - Expose namespace which VM instance exists and Intializes the Environment (callHandler)
8 * - Provides some built in contract (runTx, runBlock)
9 * - Provides resource sharing and limiting via gas
10 *
11 * All State should be stored in the Environment.
12 *
13 */
14
15// The Kernel Exposes this Interface to VM instances it makes
16const Interface = require('./interface.js')
17
18// The Kernel Stores all of its state in the Environment. The Interface is used
19// to by the VM to retrive infromation from the Environment.
20const Environment = require('./environment.js')
21
22const DebugInterface = require('./debugInterface.js')
23
24const Utils = require('./utils.js')
25
26module.exports = class Kernel {
27 // runs some code in the VM
28 constructor (environment = new Environment()) {
29 this.environment = environment
30 }
31
32 // handles running code.
33 // NOTE: it assumes that wasm will raise an exception if something went wrong,
34 // otherwise execution succeeded
35 codeHandler (code, ethInterface = new Interface(new Environment())) {
36 const debugInterface = new DebugInterface(ethInterface.environment)
37
38 const instance = Wasm.instantiateModule(code, {
39 'ethereum': ethInterface.exportTable,
40 'debug': debugInterface.exportTable,
41
42 // export this for Rust
43 // FIXME: remove once Rust has proper imports, see https://github.com/ethereum/evm2.0-design/issues/15
44 'spectest': ethInterface.exportTable,
45
46 // export this for Binaryen
47 // FIXME: remove once C has proper imports, see https://github.com/ethereum/evm2.0-design/issues/16
48 'env': ethInterface.exportTable
49 })
50
51 ethInterface.setModule(instance)
52 debugInterface.setModule(instance)
53
54 if (instance.exports.main) {
55 instance.exports.main()
56 }
57 return instance
58 }
59
60 // loads code from the merkle trie and delegates the message
61 // Detects if code is EVM or WASM
62 // Detects if the code injection is needed
63 // Detects if transcompilation is needed
64 callHandler (address, gaslimit, gasprice, value, data) {
65 var account = this.environment.state.get(new Uint8Array(address).toString())
66 if (!account) {
67 throw new Error('Account not found')
68 }
69
70 const code = this.environment.state.get(account.codeHash)
71
72 if (!code) {
73 throw new Error('Contract not found')
74 }
75
76 if (!Utils.isWASMCode(code)) {
77 throw new Error('Not an eWASM contract')
78 }
79
80 // creats a new Kernel
81 const environment = new Environment(data)
82 environment.parent = this
83
84 //environment.setCallHandler(callHandler)
85
86 const kernel = new Kernel(this, environment)
87 kernel.codeHandler(code, new Interface(environment))
88
89 // generate new stateroot
90 //this.environment.state.set(address, { stateRoot: stateRoot })
91
92 return {
93 executionOutcome: 1, // success
94 gasLeft: environment.gasLimit, // this starts as the limit and results as the gas left
95 gasRefund: environment.gasRefund,
96 returnValue: environment.returnValue,
97 selfDestructAddress: environment.selfDestructAddress,
98 logs: environment.logs
99 }
100 }
101
102 // run tx; the tx message handler
103 runTx (tx, environment = new Environment()) {
104 // verify tx then send to call Handler
105 // - from account has enough balance
106 // - check nonce
107 // - ecrecover
108 // new ethTx(tx).validate(tx)
109 // - reduce balance
110
111 this.environment = environment
112
113 // Contract deployment
114 //const isDeployment = tx.data && !tx.to;
115 //if (isDeployment) {
116 // this.environment.accounts.set(new Uint8Array())
117 //}
118
119 //
120 // environment.state - the merkle tree
121 // key: address (20 byte, hex string, without 0x prefix)
122 // every path has an account
123 //
124 // { balance, codeHash, stateRoot }
125 //
126
127 // look up sender
128 let fromAccount = this.environment.state.get(new Uint8Array(tx.form).toString())
129
130 // deduct gasLimit * gasPrice from sender
131 if (fromAccount.balance < (tx.gasLimit * tx.gasPrice)) {
132 throw new Error('Insufficient account balance')
133 }
134
135 fromAccount.balance -= ts.gasLimit * tx.gasPrice
136
137 let ret = this.callHandler(tx.to, tx.gasLimit, tx.gasPrice, tx.value, tx.data)
138
139 // refund gas
140 if (ret.executionOutcome === 1) {
141 fromAccount.balance += (ret.gasLeft + ret.gasRefund) * tx.gasPrice
142 }
143
144 // save new state?
145
146 return {
147 returnValue: ret.returnValue,
148 gasLeft: ret.gasLeft,
149 logs: ret.logs
150 }
151 }
152
153 // run block; the block message handler
154 runBlock (block, environment = new Environment()) {
155 // verify block then run each tx
156 block.tx.forEach((tx) => {
157 this.runTx(tx, environment)
158 })
159 }
160
161 // run blockchain
162 // runBlockchain () {}
163}
164

Built with git-ssb-web