git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: a925d24ca2819ab0d5702e2877d76981bcd7b285

Files: a925d24ca2819ab0d5702e2877d76981bcd7b285 / interface.js

11566 bytesRaw
1/**
2 * This is the Ethereum interface that is exposed to the WASM instance which
3 * enables to interact with the Ethereum Environment
4 */
5const Environment = require('./environment.js')
6const constants = require('./constants.js')
7
8// function.bind is not working corretly whith Wasm imports. So instead create
9// a global for now. TODO REMOVE
10let ENV
11let MOD
12// The interface exposed to the WebAessembly Core
13module.exports = class Interface {
14
15 debugPrint (a) {
16 console.log(a)
17 }
18
19 memPrint () {
20 console.log((new Uint8Array(MOD.exports.memory)).toString())
21 }
22
23 constructor (environment = new Environment()) {
24 ENV = this.environment = environment
25 }
26
27 setModule (mod) {
28 this.module = MOD = mod
29 }
30
31 /**
32 * Subtracts an amount to the gas counter
33 * @param {integer} amount the amount to subtract to the gas counter
34 */
35 useGas (amount) {
36 if (amount > 0) {
37 ENV.gasLimit -= amount
38 }
39 }
40
41 /**
42 * Returns the current amount of gas
43 * @return {integer}
44 */
45 gas () {
46 return ENV.gasLimit
47 }
48
49 /**
50 * Gets address of currently executing account and loads it into memory at
51 * the given offset.
52 * @param {integer} offset
53 */
54 address (offset) {
55 const address = ENV.address
56 const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
57 memory.set(address)
58 }
59
60 /**
61 * Gets balance of the given account and loads it into memory at the given
62 * offset.
63 * @param {integer} addressOffset the memory offset to laod the address
64 * @param {integer} resultOffset
65 */
66 balance (addressOffset, offset) {
67 const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
68 const memory = new Uint8Array(MOD.exports.memory, offset, constants.MAX_BAL_BYTES)
69 const balance = ENV.getBalance(address)
70 memory.set(balance)
71 }
72
73 /**
74 * Gets the execution's origination address and loads it into memory at the
75 * given offset. This is the sender of original transaction; it is never an
76 * account with non-empty associated code.
77 * @param {integer} offset
78 */
79 origin (offset) {
80 const origin = ENV.origin
81 const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
82 memory.set(origin)
83 }
84
85 /**
86 * Gets caller address and loads it into memory at the given offset. This is
87 * the address of the account that is directly responsible for this execution.
88 * @param {integer} offset
89 */
90 caller (offset) {
91 const caller = ENV.caller
92 const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
93 memory.set(caller)
94 }
95
96 /**
97 * Gets the deposited value by the instruction/transaction responsible for
98 * this execution and loads it into memory at the given location.
99 * @param {integer} offset
100 */
101 callValue (offset) {
102 const callValue = ENV.callValue
103 const memory = new Uint8Array(MOD.exports.memory, offset, constants.MAX_BAL_BYTES)
104 memory.set(callValue)
105 }
106
107 /**
108 * Get size of input data in current environment. This pertains to the input
109 * data passed with the message call instruction or transaction.
110 * @return {integer}
111 */
112 callDataSize () {
113 return ENV.callData.byteLength
114 }
115
116 /**
117 * Copys the input data in current environment to memory. This pertains to
118 * the input data passed with the message call instruction or transaction.
119 * @param {integer} offset the offset in memory to load into
120 * @param {integer} dataOffset the offset in the input data
121 * @param {integer} length the length of data to copy
122 */
123 callDataCopy (offset, dataOffset, length) {
124 const callData = new Uint8Array(ENV.callData, offset, length)
125 const memory = new Uint8Array(MOD.exports.memory, offset, length)
126 memory.set(callData)
127 }
128
129 /**
130 * Gets the size of code running in current environment.
131 * @return {interger}
132 */
133 codeSize () {
134 return ENV.code.byteLength
135 }
136
137 /**
138 * Copys the code running in current environment to memory.
139 * @param {integer} offset the memory offset
140 * @param {integer} codeOffset the code offset
141 * @param {integer} length the length of code to copy
142 */
143 codeCopy (offset, codeOffset, length) {
144 const code = new Uint8Array(ENV.code, codeOffset, length)
145 const memory = new Uint8Array(MOD.exports.memory, offset, length)
146 memory.set(code)
147 }
148
149 /**
150 * Get size of an account’s code.
151 * @param {integer} addressOffset the offset in memory to load the address from
152 * @return {integer}
153 */
154 extCodeSize (addressOffset) {
155 const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
156 const code = this.environment.getCode(address)
157 return code.byteLength
158 }
159
160 /**
161 * Copys the code of an account to memory.
162 * @param {integer} addressOffset the memory offset of the address
163 * @param {integer} offset the memory offset
164 * @param {integer} codeOffset the code offset
165 * @param {integer} length the length of code to copy
166 */
167 extCodeCopy (addressOffset, offset, codeOffset, length) {
168 const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
169 let code = this.environment.getCode(address)
170 code = new Uint8Array(code, codeOffset, length)
171 const memory = new Uint8Array(MOD.exports.memory, offset, length)
172 memory.set(code)
173 }
174
175 /**
176 * Gets price of gas in current environment.
177 * @return {integer}
178 */
179 gasPrice () {
180 return ENV.gasPrice
181 }
182
183 /**
184 * Gets the hash of one of the 256 most recent complete blocks.
185 * @param {integer} number which block to load
186 * @param {integer} offset the offset to load the hash into
187 */
188 blockHash (number, offset) {
189 const hash = this.environment.getBlockHash(number)
190 const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
191 memory.set(hash)
192 }
193
194 /**
195 * Gets the block’s beneficiary address and loads into memory.
196 * @param offset
197 */
198 coinbase (offset) {
199 const memory = new Uint8Array(MOD.exports.memory, offset, constants.ADD_SIZE_BYTES)
200 memory.set(ENV.coinbase)
201 }
202
203 /**
204 * Get the block’s timestamp.
205 * @return {integer}
206 */
207 timestamp () {
208 return ENV.timestamp
209 }
210
211 /**
212 * Get the block’s number.
213 * @return {integer}
214 */
215 number () {
216 return ENV.number
217 }
218
219 /**
220 * Get the block’s difficulty.
221 * @return {integer}
222 */
223 difficulty () {
224 return ENV.difficulty
225 }
226
227 /**
228 * Get the block’s gas limit.
229 * @return {integer}
230 */
231 gasLimit () {
232 return ENV.gasLimit
233 }
234
235 /**
236 * Creates a new log in the current environment
237 * @param {integer} dataOffset the offset in memory to load the memory
238 * @param {integer} length the data length
239 * TODO: replace with variadic
240 */
241 log (dataOffset, length, topic1, topic2, topic3, topic4, topic5) {
242 const data = new Uint8Array(MOD.exports.memory, dataOffset, length)
243 ENV.logs.push({
244 data: data,
245 topics: [topic1, topic2, topic3, topic4, topic5]
246 })
247 }
248
249 /**
250 * Creates a new contract with a given value.
251 * @param {integer} valueOffset the offset in memory to the value from
252 * @param {integer} dataOffset the offset to load the code for the new contract from
253 * @param {integer} length the data length
254 */
255 create (valueOffset, dataOffset, length) {
256 const value = new Uint8Array(MOD.exports.memory, valueOffset, constants.MAX_BAL_BYTES)
257 const data = new Uint8Array(MOD.exports.memory, dataOffset, length)
258 const result = ENV.create(value, data)
259 return result
260 }
261
262 /**
263 * Sends a message with arbiatary data to a given address path
264 * @param {integer} addressOffset the offset to load the address path from
265 * @param {integer} valueOffset the offset to load the value from
266 * @param {integer} dataOffset the offset to load data from
267 * @param {integer} dataLength the length of data
268 * @param {integer} resultOffset the offset to store the result data at
269 * @param {integer} resultLength
270 * @param {integer} gas
271 * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
272 * TODO: add proper gas counting
273 */
274 call (addressOffset, valueOffset, dataOffset, dataLength, resultOffset, resultLength, gas) {
275 if (gas === undefined) {
276 gas = this.gasLeft()
277 }
278 // Load the params from mem
279 const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
280 const value = new Uint8Array(MOD.exports.memory, valueOffset, constants.MAX_BAL_BYTES)
281 const data = new Uint8Array(MOD.exports.memory, dataOffset, dataLength)
282 // Run the call
283 const [result, errorCode] = ENV.call(gas, address, value, data)
284 const memory = new Uint8Array(MOD.exports.memory, resultOffset, resultLength)
285 memory.set(result)
286
287 return errorCode
288 }
289
290 /**
291 * Message-call into this account with an alternative account’s code, but
292 * persisting the current values for sender and value.
293 * @param {integer} gas
294 * @param {integer} addressOffset the offset to load the address path from
295 * @param {integer} valueOffset the offset to load the value from
296 * @param {integer} dataOffset the offset to load data from
297 * @param {integer} dataLength the length of data
298 * @param {integer} resultOffset the offset to store the result data at
299 * @param {integer} resultLength
300 * @return {integer} Returns 1 or 0 depending on if the VM trapped on the message or not
301 */
302 callDelegate (gas, addressOffset, dataOffset, dataLength, resultOffset, resultLength) {
303 const data = new Uint8Array(MOD.exports.memory, dataOffset, dataLength)
304 const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
305 const [result, errorCode] = this.environment.callDelegate(gas, address, data)
306 const memory = new Uint8Array(MOD.exports.memory, resultOffset, resultLength)
307 memory.set(result)
308
309 return errorCode
310 }
311
312 /**
313 * store a value at a given path in long term storage which are both loaded
314 * from Memory
315 * @param {interger} pathOffest the memory offset to load the the path from
316 * @param {interger} valueOffset the memory offset to load the value from
317 */
318 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 }
323
324 /**
325 * reterives a value at a given path in long term storage
326 * @param {interger} pathOffest the memory offset to load the the path from
327 * @param {interger} resultOffset the memory offset to load the value from
328 */
329 sload (pathOffest, resultOffset) {
330 const path = new Uint8Array(MOD.exports.memory, pathOffest, 32)
331 const result = ENV.state.getValue(path)
332 const memory = new Uint8Array(MOD.exports.memory, resultOffset, 32)
333 memory.set(result)
334 }
335
336 /**
337 * Halt execution returning output data.
338 * @param {integer} offset the offset of the output data.
339 * @param {integer} length the length of the output data.
340 */
341 return (offset, length) {
342 this.environment.returnValue = new Uint8Array(MOD.exports.memory, offset, length)
343 }
344
345 /**
346 * Halt execution and register account for later deletion giving the remaining
347 * balance to an address path
348 * @param {integer} offset the offset to load the address from
349 */
350 suicide (addressOffset) {
351 const address = new Uint8Array(MOD.exports.memory, addressOffset, constants.ADD_SIZE_BYTES)
352 this.environment.suicideAddress = address
353 }
354}
355

Built with git-ssb-web