git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 4fab50d68a1e30515e707a71ab11d420f18fd7a7

Files: 4fab50d68a1e30515e707a71ab11d420f18fd7a7 / interface.js

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

Built with git-ssb-web