git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: af08dc3e0ce5be82ca5f4be87523656ed6ce5498

Files: af08dc3e0ce5be82ca5f4be87523656ed6ce5498 / index.js

4839 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 toAccount = this.environment.accounts.get(new Uint8Array(address).toString())
66 if (!toAccount) {
67 throw new Error('Account not found')
68 }
69
70 // creats a new Kernel
71 const environment = new Environment(data)
72 environment.parent = this
73 const kernel = new Kernel(this, environment)
74 const code = this.environment.state.get(address)
75
76 //environment.setCallHandler(callHandler)
77
78 if (!code) {
79 throw new Error('Contract not found')
80 }
81 if (!Utils.isWASMCode(code)) {
82 throw new Error('Not an eWASM contract')
83 }
84 kernel.codeHandler(code, new Interface(environment))
85
86 // generate new stateroot
87 //this.environment.state.set(address, { stateRoot: stateRoot })
88
89 return {
90 executionOutcome: 1, // success
91 gasLeft: 0,
92 gasRefunds: 0,
93 returnValue: new ArrayBuffer(),
94 selfDestructAddress: new Uint8Array(),
95 logs: []
96 }
97 }
98
99 // run tx; the tx message handler
100 runTx (tx, environment = new Environment()) {
101 // verify tx then send to call Handler
102 // - from account has enough balance
103 // - check nonce
104 // - ecrecover
105 // new ethTx(tx).validate(tx)
106 // - reduce balance
107
108 this.environment = environment
109
110 // Contract deployment
111 //const isDeployment = tx.data && !tx.to;
112 //if (isDeployment) {
113 // this.environment.accounts.set(new Uint8Array())
114 //}
115
116 //
117 // environment.state - the merkle tree
118 // key: address (20 byte, hex string, without 0x prefix)
119 // every path has an account
120 //
121 // { balance, codeHash, stateRoot }
122 //
123
124 // look up sender
125 let fromAccount = this.environment.accounts.get(new Uint8Array(tx.form).toString())
126
127 // deduct gasLimit * gasPrice from sender
128 if (fromAccount.balance < (tx.gasLimit * tx.gasPrice)) {
129 throw new Error('Insufficient account balance')
130 }
131
132 fromAccount.balance -= ts.gasLimit * tx.gasPrice
133
134 let ret = this.callHandler(tx.to, tx.gasLimit, tx.gasPrice, tx.value, tx.data)
135
136 // refund gas
137 if (ret.executionOutcome === 1) {
138 fromAccount.balance += (ret.gasLeft + ret.gasRefund) * tx.gasPrice
139 }
140
141 // save new state?
142
143 return {
144 returnValue: ret.returnValue,
145 gasLeft: ret.gasLeft,
146 logs: ret.logs
147 }
148 }
149
150 // run block; the block message handler
151 runBlock (block, environment = new Environment()) {
152 // verify block then run each tx
153 block.tx.forEach((tx) => {
154 this.runTx(tx, environment)
155 })
156 }
157
158 // run blockchain
159 // runBlockchain () {}
160}
161

Built with git-ssb-web