git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 0edfe5b10a3a58691d782ae18e443689a66cf95d

Files: 0edfe5b10a3a58691d782ae18e443689a66cf95d / interface.js

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

Built with git-ssb-web