git ssb

0+

wanderer🌟 / js-primea-hypervisor



Tree: 76b626ab5a6d24e48ccefffb8900dc9052b0b36d

Files: 76b626ab5a6d24e48ccefffb8900dc9052b0b36d / interface.js

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

Built with git-ssb-web