@feelyourprotocol/vm 8141.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +583 -0
  3. package/dist/cjs/bloom/index.d.ts +29 -0
  4. package/dist/cjs/bloom/index.d.ts.map +1 -0
  5. package/dist/cjs/bloom/index.js +76 -0
  6. package/dist/cjs/bloom/index.js.map +1 -0
  7. package/dist/cjs/buildBlock.d.ts +118 -0
  8. package/dist/cjs/buildBlock.d.ts.map +1 -0
  9. package/dist/cjs/buildBlock.js +363 -0
  10. package/dist/cjs/buildBlock.js.map +1 -0
  11. package/dist/cjs/constructors.d.ts +9 -0
  12. package/dist/cjs/constructors.d.ts.map +1 -0
  13. package/dist/cjs/constructors.js +75 -0
  14. package/dist/cjs/constructors.js.map +1 -0
  15. package/dist/cjs/emitEVMProfile.d.ts +9 -0
  16. package/dist/cjs/emitEVMProfile.d.ts.map +1 -0
  17. package/dist/cjs/emitEVMProfile.js +130 -0
  18. package/dist/cjs/emitEVMProfile.js.map +1 -0
  19. package/dist/cjs/index.d.ts +11 -0
  20. package/dist/cjs/index.d.ts.map +1 -0
  21. package/dist/cjs/index.js +36 -0
  22. package/dist/cjs/index.js.map +1 -0
  23. package/dist/cjs/package.json +3 -0
  24. package/dist/cjs/params.d.ts +3 -0
  25. package/dist/cjs/params.d.ts.map +1 -0
  26. package/dist/cjs/params.js +105 -0
  27. package/dist/cjs/params.js.map +1 -0
  28. package/dist/cjs/requests.d.ts +11 -0
  29. package/dist/cjs/requests.d.ts.map +1 -0
  30. package/dist/cjs/requests.js +208 -0
  31. package/dist/cjs/requests.js.map +1 -0
  32. package/dist/cjs/runBlock.d.ts +35 -0
  33. package/dist/cjs/runBlock.d.ts.map +1 -0
  34. package/dist/cjs/runBlock.js +797 -0
  35. package/dist/cjs/runBlock.js.map +1 -0
  36. package/dist/cjs/runFrameTx.d.ts +18 -0
  37. package/dist/cjs/runFrameTx.d.ts.map +1 -0
  38. package/dist/cjs/runFrameTx.js +313 -0
  39. package/dist/cjs/runFrameTx.js.map +1 -0
  40. package/dist/cjs/runTx.d.ts +18 -0
  41. package/dist/cjs/runTx.d.ts.map +1 -0
  42. package/dist/cjs/runTx.js +900 -0
  43. package/dist/cjs/runTx.js.map +1 -0
  44. package/dist/cjs/types.d.ts +452 -0
  45. package/dist/cjs/types.d.ts.map +1 -0
  46. package/dist/cjs/types.js +3 -0
  47. package/dist/cjs/types.js.map +1 -0
  48. package/dist/cjs/vm.d.ts +75 -0
  49. package/dist/cjs/vm.d.ts.map +1 -0
  50. package/dist/cjs/vm.js +111 -0
  51. package/dist/cjs/vm.js.map +1 -0
  52. package/dist/esm/bloom/index.d.ts +29 -0
  53. package/dist/esm/bloom/index.d.ts.map +1 -0
  54. package/dist/esm/bloom/index.js +72 -0
  55. package/dist/esm/bloom/index.js.map +1 -0
  56. package/dist/esm/buildBlock.d.ts +118 -0
  57. package/dist/esm/buildBlock.d.ts.map +1 -0
  58. package/dist/esm/buildBlock.js +358 -0
  59. package/dist/esm/buildBlock.js.map +1 -0
  60. package/dist/esm/constructors.d.ts +9 -0
  61. package/dist/esm/constructors.d.ts.map +1 -0
  62. package/dist/esm/constructors.js +72 -0
  63. package/dist/esm/constructors.js.map +1 -0
  64. package/dist/esm/emitEVMProfile.d.ts +9 -0
  65. package/dist/esm/emitEVMProfile.d.ts.map +1 -0
  66. package/dist/esm/emitEVMProfile.js +127 -0
  67. package/dist/esm/emitEVMProfile.js.map +1 -0
  68. package/dist/esm/index.d.ts +11 -0
  69. package/dist/esm/index.d.ts.map +1 -0
  70. package/dist/esm/index.js +11 -0
  71. package/dist/esm/index.js.map +1 -0
  72. package/dist/esm/package.json +3 -0
  73. package/dist/esm/params.d.ts +3 -0
  74. package/dist/esm/params.d.ts.map +1 -0
  75. package/dist/esm/params.js +102 -0
  76. package/dist/esm/params.js.map +1 -0
  77. package/dist/esm/requests.d.ts +11 -0
  78. package/dist/esm/requests.d.ts.map +1 -0
  79. package/dist/esm/requests.js +204 -0
  80. package/dist/esm/requests.js.map +1 -0
  81. package/dist/esm/runBlock.d.ts +35 -0
  82. package/dist/esm/runBlock.d.ts.map +1 -0
  83. package/dist/esm/runBlock.js +790 -0
  84. package/dist/esm/runBlock.js.map +1 -0
  85. package/dist/esm/runFrameTx.d.ts +18 -0
  86. package/dist/esm/runFrameTx.d.ts.map +1 -0
  87. package/dist/esm/runFrameTx.js +310 -0
  88. package/dist/esm/runFrameTx.js.map +1 -0
  89. package/dist/esm/runTx.d.ts +18 -0
  90. package/dist/esm/runTx.d.ts.map +1 -0
  91. package/dist/esm/runTx.js +896 -0
  92. package/dist/esm/runTx.js.map +1 -0
  93. package/dist/esm/types.d.ts +452 -0
  94. package/dist/esm/types.d.ts.map +1 -0
  95. package/dist/esm/types.js +2 -0
  96. package/dist/esm/types.js.map +1 -0
  97. package/dist/esm/vm.d.ts +75 -0
  98. package/dist/esm/vm.d.ts.map +1 -0
  99. package/dist/esm/vm.js +107 -0
  100. package/dist/esm/vm.js.map +1 -0
  101. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  102. package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
  103. package/package.json +117 -0
  104. package/src/bloom/index.ts +83 -0
  105. package/src/buildBlock.ts +470 -0
  106. package/src/constructors.ts +91 -0
  107. package/src/emitEVMProfile.ts +151 -0
  108. package/src/index.ts +10 -0
  109. package/src/params.ts +104 -0
  110. package/src/requests.ts +293 -0
  111. package/src/runBlock.ts +1022 -0
  112. package/src/runFrameTx.ts +411 -0
  113. package/src/runTx.ts +1203 -0
  114. package/src/types.ts +511 -0
  115. package/src/vm.ts +147 -0
package/src/types.ts ADDED
@@ -0,0 +1,511 @@
1
+ import type { Block, BlockOptions, HeaderData } from '@feelyourprotocol/block'
2
+ import type { Common, ParamsDict, StateManagerInterface } from '@feelyourprotocol/common'
3
+ import type {
4
+ EVMInterface,
5
+ EVMMockBlockchainInterface,
6
+ EVMOpts,
7
+ EVMResult,
8
+ Log,
9
+ } from '@feelyourprotocol/evm'
10
+ import type { AccessList, TypedTransaction } from '@feelyourprotocol/tx'
11
+ import type {
12
+ BigIntLike,
13
+ BlockLevelAccessList,
14
+ CLRequest,
15
+ CLRequestType,
16
+ PrefixedHexString,
17
+ WithdrawalData,
18
+ } from '@feelyourprotocol/util'
19
+ import type { Bloom } from './bloom/index.ts'
20
+ export type TxReceipt = PreByzantiumTxReceipt | PostByzantiumTxReceipt | EIP4844BlobTxReceipt
21
+
22
+ /**
23
+ * Abstract interface with common transaction receipt fields
24
+ */
25
+ export interface BaseTxReceipt {
26
+ /**
27
+ * Cumulative gas used in the block including this tx
28
+ */
29
+ cumulativeBlockGasUsed: bigint
30
+ /**
31
+ * Bloom bitvector
32
+ */
33
+ bitvector: Uint8Array
34
+ /**
35
+ * Logs emitted
36
+ */
37
+ logs: Log[]
38
+ }
39
+
40
+ /**
41
+ * Pre-Byzantium receipt type with a field
42
+ * for the intermediary state root
43
+ */
44
+ export interface PreByzantiumTxReceipt extends BaseTxReceipt {
45
+ /**
46
+ * Intermediary state root
47
+ */
48
+ stateRoot: Uint8Array
49
+ }
50
+
51
+ /**
52
+ * Receipt type for Byzantium and beyond replacing the intermediary
53
+ * state root field with a status code field (EIP-658)
54
+ */
55
+ export interface PostByzantiumTxReceipt extends BaseTxReceipt {
56
+ /**
57
+ * Status of transaction, `1` if successful, `0` if an exception occurred
58
+ */
59
+ status: 0 | 1
60
+ }
61
+
62
+ export interface EIP4844BlobTxReceipt extends PostByzantiumTxReceipt {
63
+ /**
64
+ * blob gas consumed by a transaction
65
+ *
66
+ * Note: This value is not included in the receiptRLP used for encoding the receiptsRoot in a block
67
+ * and is only provided as part of receipt metadata.
68
+ */
69
+ blobGasUsed: bigint
70
+ /**
71
+ * blob gas price for block transaction was included in
72
+ *
73
+ * Note: This values is not included in the `receiptRLP` used for encoding the `receiptsRoot` in a block
74
+ * and is only provided as part of receipt metadata.
75
+ */
76
+ blobGasPrice: bigint
77
+ }
78
+
79
+ export type EVMProfilerOpts = {
80
+ enabled: boolean
81
+ // extra options here (such as use X hardfork for gas)
82
+ }
83
+
84
+ export type VMEvent = {
85
+ beforeBlock: (data: Block, resolve?: (result?: any) => void) => void
86
+ afterBlock: (data: AfterBlockEvent, resolve?: (result?: any) => void) => void
87
+ beforeTx: (data: TypedTransaction, resolve?: (result?: any) => void) => void
88
+ afterTx: (data: AfterTxEvent, resolve?: (result?: any) => void) => void
89
+ }
90
+
91
+ export type VMProfilerOpts = {
92
+ //evmProfilerOpts: EVMProfilerOpts
93
+ reportAfterTx?: boolean
94
+ reportAfterBlock?: boolean
95
+ }
96
+
97
+ /**
98
+ * Options for instantiating a {@link VM}.
99
+ */
100
+ export interface VMOpts {
101
+ /**
102
+ * Use a {@link Common} instance
103
+ * if you want to change the chain setup.
104
+ *
105
+ * ### Possible Values
106
+ *
107
+ * - `chain`: all chains supported by `Common` or a custom chain
108
+ * - `hardfork`: `mainnet` hardforks up to the `Paris` hardfork
109
+ * - `eips`: `2537` (usage e.g. `eips: [ 2537, ]`)
110
+ *
111
+ * Note: check the associated `@feelyourprotocol/evm` instance options
112
+ * documentation for supported EIPs.
113
+ *
114
+ * ### Default Setup
115
+ *
116
+ * Default setup if no `Common` instance is provided:
117
+ *
118
+ * - `chain`: `mainnet`
119
+ * - `hardfork`: `paris`
120
+ * - `eips`: `[]`
121
+ */
122
+ common?: Common
123
+ /**
124
+ * A {@link StateManager} instance to use as the state store
125
+ */
126
+ stateManager?: StateManagerInterface
127
+ /**
128
+ * A {@link Blockchain} object for storing/retrieving blocks
129
+ */
130
+ blockchain?: EVMMockBlockchainInterface
131
+ /**
132
+ * If true, create entries in the state tree for the precompiled contracts, saving some gas the
133
+ * first time each of them is called.
134
+ *
135
+ * If this parameter is false, each call to each of them has to pay an extra 25000 gas
136
+ * for creating the account. If the account is still empty after this call, it will be deleted,
137
+ * such that this extra cost has to be paid again.
138
+ *
139
+ * Setting this to true has the effect of precompiled contracts' gas costs matching mainnet's from
140
+ * the very first call, which is intended for testing networks.
141
+ *
142
+ * Default: `false`
143
+ */
144
+ activatePrecompiles?: boolean
145
+
146
+ /**
147
+ * Set the hardfork either by timestamp (for HFs from Shanghai onwards) or by block number
148
+ * for older Hfs.
149
+ *
150
+ * Additionally it is possible to pass in a specific TD value to support live-Merge-HF
151
+ * transitions. Note that this should only be needed in very rare and specific scenarios.
152
+ *
153
+ * Default: `false` (HF is set to whatever default HF is set by the {@link Common} instance)
154
+ */
155
+ setHardfork?: boolean | BigIntLike
156
+ /**
157
+ * VM parameters sorted by EIP can be found in the exported `paramsVM` dictionary,
158
+ * which is internally passed to the associated `@feelyourprotocol/common` instance which
159
+ * manages parameter selection based on the hardfork and EIP settings.
160
+ *
161
+ * This option allows providing a custom set of parameters. Note that parameters
162
+ * get fully overwritten, so you need to extend the default parameter dict
163
+ * to provide the full parameter set.
164
+ *
165
+ * It is recommended to deep-clone the params object for this to avoid side effects:
166
+ *
167
+ * ```ts
168
+ * const params = JSON.parse(JSON.stringify(paramsVM))
169
+ * params['1559']['elasticityMultiplier'] = 10 // 2
170
+ * ```
171
+ */
172
+ params?: ParamsDict
173
+
174
+ /**
175
+ * Use a custom EVM to run Messages on. If this is not present, use the default EVM.
176
+ */
177
+ evm?: EVMInterface
178
+
179
+ /**
180
+ * Often there is no need to provide a full custom EVM but only a few options need to be
181
+ * adopted. This option allows to provide a custom set of EVM options to be passed.
182
+ *
183
+ * Note: This option will throw if used in conjunction with a full custom EVM passed.
184
+ */
185
+ evmOpts?: EVMOpts
186
+
187
+ profilerOpts?: VMProfilerOpts
188
+ }
189
+
190
+ /**
191
+ * Options for the block builder.
192
+ */
193
+ export interface BuilderOpts extends BlockOptions {
194
+ /**
195
+ * Whether to put the block into the vm's blockchain after building it.
196
+ * This is useful for completing a full cycle when building a block so
197
+ * the only next step is to build again, however it may not be desired
198
+ * if the block is being emulated or may be discarded as to not affect
199
+ * the underlying blockchain.
200
+ *
201
+ * Default: true
202
+ */
203
+ putBlockIntoBlockchain?: boolean
204
+ /**
205
+ * Provide a clique signer's privateKey to seal this block.
206
+ * Will throw if provided on a non-PoA chain.
207
+ */
208
+ cliqueSigner?: Uint8Array
209
+ }
210
+
211
+ /**
212
+ * Options for building a block.
213
+ */
214
+ export interface BuildBlockOpts {
215
+ /**
216
+ * The parent block
217
+ */
218
+ parentBlock: Block
219
+
220
+ /**
221
+ * The block header data to use.
222
+ * Defaults used for any values not provided.
223
+ */
224
+ headerData?: HeaderData
225
+
226
+ withdrawals?: WithdrawalData[]
227
+ /**
228
+ * The block and builder options to use.
229
+ */
230
+ blockOpts?: BuilderOpts
231
+ }
232
+
233
+ /**
234
+ * Options for sealing a block.
235
+ */
236
+ export interface SealBlockOpts {
237
+ /**
238
+ * For PoW, the nonce.
239
+ * Overrides the value passed in the constructor.
240
+ */
241
+ nonce?: Uint8Array
242
+
243
+ /**
244
+ * For PoW, the mixHash.
245
+ * Overrides the value passed in the constructor.
246
+ */
247
+ mixHash?: Uint8Array
248
+ }
249
+
250
+ /**
251
+ * Options for running a block.
252
+ */
253
+ export interface RunBlockOpts {
254
+ /**
255
+ * The @feelyourprotocol/block to process
256
+ */
257
+ block: Block
258
+ /**
259
+ * Root of the state trie
260
+ */
261
+ root?: Uint8Array
262
+ /**
263
+ * Clearing the StateManager cache.
264
+ *
265
+ * If state root is not reset for whatever reason this can be set to `false` for better performance.
266
+ *
267
+ * Default: true
268
+ */
269
+ clearCache?: boolean
270
+ /**
271
+ * Whether to generate the stateRoot and other related fields.
272
+ * If `true`, `runBlock` will set the fields `stateRoot`, `receiptTrie`, `gasUsed`, and `bloom` (logs bloom) after running the block.
273
+ * If `false`, `runBlock` throws if any fields do not match.
274
+ * Defaults to `false`.
275
+ */
276
+ generate?: boolean
277
+
278
+ /**
279
+ * If true, will skip "Block validation":
280
+ * Block validation validates the header (with respect to the blockchain),
281
+ * the transactions, the transaction trie and the uncle hash.
282
+ */
283
+ skipBlockValidation?: boolean
284
+ /**
285
+ * If true, skips the hardfork validation of vm, block
286
+ * and tx
287
+ */
288
+ skipHardForkValidation?: boolean
289
+ /**
290
+ * if true, will skip "Header validation"
291
+ * If the block has been picked from the blockchain to be executed,
292
+ * header has already been validated, and can be skipped especially when
293
+ * consensus of the chain has moved ahead.
294
+ */
295
+ skipHeaderValidation?: boolean
296
+ /**
297
+ * If true, skips the nonce check
298
+ */
299
+ skipNonce?: boolean
300
+ /**
301
+ * If true, checks the balance of the `from` account for the transaction and sets its
302
+ * balance equal equal to the upfront cost (gas limit * gas price + transaction value)
303
+ */
304
+ skipBalance?: boolean
305
+ /**
306
+ * Set the hardfork either by timestamp (for HFs from Shanghai onwards) or by block number
307
+ * for older Hfs.
308
+ *
309
+ * Default: `false` (HF is set to whatever default HF is set by the {@link Common} instance)
310
+ */
311
+ setHardfork?: boolean
312
+
313
+ /**
314
+ * If true, adds a hashedKey -> preimages mapping of all touched accounts
315
+ * to the `RunTxResult` returned.
316
+ */
317
+ reportPreimages?: boolean
318
+
319
+ /**
320
+ * If true, will validate block size limit (EIP-7934) when validating block data.
321
+ * Defaults to false.
322
+ */
323
+ validateBlockSize?: boolean
324
+ }
325
+
326
+ /**
327
+ * Result of {@link applyBlock}
328
+ */
329
+ export interface ApplyBlockResult {
330
+ /**
331
+ * The Bloom filter
332
+ */
333
+ bloom: Bloom
334
+ /**
335
+ * The gas used after executing the block
336
+ */
337
+ gasUsed: bigint
338
+ /**
339
+ * The receipt root after executing the block
340
+ */
341
+ receiptsRoot: Uint8Array
342
+ /**
343
+ * Receipts generated for transactions in the block
344
+ */
345
+ receipts: TxReceipt[]
346
+ /**
347
+ * Results of executing the transactions in the block
348
+ */
349
+ results: RunTxResult[]
350
+ /**
351
+ * Preimages mapping of the touched accounts from the block (see reportPreimages option)
352
+ */
353
+ preimages?: Map<PrefixedHexString, Uint8Array>
354
+ }
355
+
356
+ /**
357
+ * Result of {@link runBlock}
358
+ */
359
+ export interface RunBlockResult extends Omit<ApplyBlockResult, 'bloom'> {
360
+ /**
361
+ * The stateRoot after executing the block
362
+ */
363
+ stateRoot: Uint8Array
364
+ /**
365
+ * The bloom filter of the LOGs (events) after executing the block
366
+ */
367
+ logsBloom: Uint8Array
368
+
369
+ /**
370
+ * The requestsHash for any CL requests in the block
371
+ */
372
+ requestsHash?: Uint8Array
373
+ /**
374
+ * Any CL requests that were processed in the course of this block
375
+ */
376
+ requests?: CLRequest<CLRequestType>[]
377
+ /**
378
+ * The block level access list created during execution
379
+ * (if EIP-7928 is active)
380
+ */
381
+ blockLevelAccessList?: BlockLevelAccessList
382
+ }
383
+
384
+ export interface AfterBlockEvent extends RunBlockResult {
385
+ // The block which just finished processing
386
+ block: Block
387
+ }
388
+
389
+ /**
390
+ * Options for the `runTx` method.
391
+ */
392
+ export interface RunTxOpts {
393
+ /**
394
+ * The `@feelyourprotocol/block` the `tx` belongs to.
395
+ * If omitted, a default blank block will be used.
396
+ */
397
+ block?: Block
398
+ /**
399
+ * An `@feelyourprotocol/tx` to run
400
+ */
401
+ tx: TypedTransaction
402
+ /**
403
+ * If true, skips the nonce check
404
+ */
405
+ skipNonce?: boolean
406
+
407
+ /**
408
+ * Skip balance checks if true. Adds transaction cost to balance to ensure execution doesn't fail.
409
+ */
410
+ skipBalance?: boolean
411
+
412
+ /**
413
+ * If true, skips the validation of the tx's gas limit
414
+ * against the block's gas limit.
415
+ */
416
+ skipBlockGasLimitValidation?: boolean
417
+
418
+ /**
419
+ * If true, skips the hardfork validation of vm, block
420
+ * and tx
421
+ */
422
+ skipHardForkValidation?: boolean
423
+
424
+ /**
425
+ * If true, adds a generated EIP-2930 access list
426
+ * to the `RunTxResult` returned.
427
+ *
428
+ * Option works with all tx types. EIP-2929 needs to
429
+ * be activated (included in `berlin` HF).
430
+ *
431
+ * Note: if this option is used with a custom {@link StateManager} implementation
432
+ * {@link StateManager.generateAccessList} must be implemented.
433
+ */
434
+ reportAccessList?: boolean
435
+
436
+ /**
437
+ * If true, adds a hashedKey -> preimages mapping of all touched accounts
438
+ * to the `RunTxResult` returned.
439
+ */
440
+ reportPreimages?: boolean
441
+
442
+ /**
443
+ * To obtain an accurate tx receipt input the block gas used up until this tx.
444
+ */
445
+ blockGasUsed?: bigint
446
+ }
447
+
448
+ /**
449
+ * Execution result of a transaction
450
+ */
451
+ export interface RunTxResult extends EVMResult {
452
+ /**
453
+ * Bloom filter resulted from transaction
454
+ */
455
+ bloom: Bloom
456
+
457
+ /**
458
+ * The amount of ether used by this transaction
459
+ */
460
+ amountSpent: bigint
461
+
462
+ /**
463
+ * The tx receipt
464
+ */
465
+ receipt: TxReceipt
466
+
467
+ /**
468
+ * The amount of gas used in this transaction, which is paid for
469
+ * This contains the gas units that have been used on execution, plus the upfront cost,
470
+ * which consists of calldata cost, intrinsic cost and optionally the access list costs
471
+ */
472
+ totalGasSpent: bigint
473
+
474
+ /**
475
+ * The amount of gas accounted for at block level.
476
+ * On EIP-7778 this excludes tx-level refund subtraction.
477
+ */
478
+ blockGasSpent: bigint
479
+
480
+ /**
481
+ * The amount of gas as that was refunded during the transaction (i.e. `gasUsed = totalGasConsumed - gasRefund`)
482
+ */
483
+ gasRefund: bigint
484
+
485
+ /**
486
+ * EIP-2930 access list generated for the tx (see `reportAccessList` option)
487
+ */
488
+ accessList?: AccessList
489
+
490
+ /**
491
+ * Preimages mapping of the touched accounts from the tx (see `reportPreimages` option)
492
+ */
493
+ preimages?: Map<PrefixedHexString, Uint8Array>
494
+
495
+ /**
496
+ * The value that accrues to the miner by this transaction
497
+ */
498
+ minerValue: bigint
499
+
500
+ /**
501
+ * This is the blob gas units times the fee per blob gas for 4844 transactions
502
+ */
503
+ blobGasUsed?: bigint
504
+ }
505
+
506
+ export interface AfterTxEvent extends RunTxResult {
507
+ /**
508
+ * The transaction which just got finished
509
+ */
510
+ transaction: TypedTransaction
511
+ }
package/src/vm.ts ADDED
@@ -0,0 +1,147 @@
1
+ import { createEVM } from '@feelyourprotocol/evm'
2
+ import { EventEmitter } from 'eventemitter3'
3
+
4
+ import { createVM } from './constructors.ts'
5
+ import { paramsVM } from './params.ts'
6
+
7
+ import type { Common, StateManagerInterface } from '@feelyourprotocol/common'
8
+ import type { EVMInterface, EVMMockBlockchainInterface } from '@feelyourprotocol/evm'
9
+ import { isDebugEnabled } from '@feelyourprotocol/util'
10
+ import type { BigIntLike } from '@feelyourprotocol/util'
11
+ import type { VMEvent, VMOpts } from './types.ts'
12
+
13
+ /**
14
+ * The VM is a state transition machine that executes EVM bytecode and updates the state.
15
+ * It can be used to execute transactions, blocks, individual transactions, or snippets of EVM bytecode.
16
+ *
17
+ * A VM can be created with the constructor method:
18
+ *
19
+ * - {@link createVM}
20
+ */
21
+ export class VM {
22
+ /**
23
+ * The StateManager used by the VM
24
+ */
25
+ readonly stateManager: StateManagerInterface
26
+
27
+ /**
28
+ * The blockchain the VM operates on
29
+ */
30
+ readonly blockchain: EVMMockBlockchainInterface
31
+
32
+ readonly common: Common
33
+
34
+ readonly events: EventEmitter<VMEvent>
35
+ /**
36
+ * The EVM used for bytecode execution
37
+ */
38
+ readonly evm: EVMInterface
39
+
40
+ protected readonly _opts: VMOpts
41
+ protected _isInitialized: boolean = false
42
+
43
+ protected readonly _setHardfork: boolean | BigIntLike
44
+
45
+ /**
46
+ * Cached emit() function, not for public usage
47
+ * set to public due to implementation internals
48
+ * @hidden
49
+ */
50
+ public readonly _emit: (topic: string, data: any) => Promise<void>
51
+
52
+ /**
53
+ * VM is run in DEBUG mode (default: false)
54
+ * Taken from DEBUG environment variable
55
+ *
56
+ * Safeguards on debug() calls are added for
57
+ * performance reasons to avoid string literal evaluation
58
+ * @hidden
59
+ */
60
+ readonly DEBUG: boolean = false
61
+
62
+ /**
63
+ * Instantiates a new {@link VM} Object.
64
+ *
65
+ * @deprecated The direct usage of this constructor is discouraged since
66
+ * non-finalized async initialization might lead to side effects. Please
67
+ * use the async {@link createVM} constructor instead (same API).
68
+ * @param opts
69
+ */
70
+ constructor(opts: VMOpts = {}) {
71
+ this.common = opts.common!
72
+ this.common.updateParams(opts.params ?? paramsVM)
73
+ this.stateManager = opts.stateManager!
74
+ this.blockchain = opts.blockchain!
75
+ this.evm = opts.evm!
76
+
77
+ this.events = new EventEmitter<VMEvent>()
78
+
79
+ this._emit = async (topic: string, data: any): Promise<void> => {
80
+ const listeners = this.events.listeners(topic as keyof VMEvent)
81
+ for (const listener of listeners) {
82
+ if (listener.length === 2) {
83
+ await new Promise<void>((resolve) => {
84
+ listener(data, resolve)
85
+ })
86
+ } else {
87
+ listener(data)
88
+ }
89
+ }
90
+ }
91
+ this._opts = opts
92
+
93
+ this._setHardfork = opts.setHardfork ?? false
94
+
95
+ // Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables
96
+ this.DEBUG = isDebugEnabled('ethjs')
97
+ }
98
+
99
+ /**
100
+ * Returns a copy of the {@link VM} instance.
101
+ *
102
+ * Note that the returned copy will share the same db as the original for the blockchain and the statemanager.
103
+ *
104
+ * Associated caches will be deleted and caches will be re-initialized for a more short-term focused
105
+ * usage, being less memory intense (the statemanager caches will switch to using an ORDERED_MAP cache
106
+ * data structure more suitable for short-term usage, the trie node LRU cache will not be activated at all).
107
+ * To fine-tune this behavior (if the shallow-copy-returned object has a longer life span e.g.) you can set
108
+ * the `downlevelCaches` option to `false`.
109
+ *
110
+ * @param downlevelCaches Downlevel (so: adopted for short-term usage) associated state caches (default: true)
111
+ */
112
+ async shallowCopy(downlevelCaches = true): Promise<VM> {
113
+ const common = this.common.copy()
114
+ common.setHardfork(this.common.hardfork())
115
+ const blockchain = this.blockchain.shallowCopy()
116
+ const stateManager = this.stateManager.shallowCopy(downlevelCaches)
117
+ const evmOpts = {
118
+ ...(this.evm as any)._optsCached,
119
+ common: this._opts.evmOpts?.common?.copy() ?? common,
120
+ blockchain: this._opts.evmOpts?.blockchain?.shallowCopy() ?? blockchain,
121
+ stateManager: this._opts.evmOpts?.stateManager?.shallowCopy(downlevelCaches) ?? stateManager,
122
+ }
123
+ const evmCopy = await createEVM(evmOpts) // TODO fixme (should copy the EVMInterface, not default EVM)
124
+ return createVM({
125
+ stateManager,
126
+ blockchain: this.blockchain,
127
+ common,
128
+ evm: evmCopy,
129
+ setHardfork: this._setHardfork,
130
+ profilerOpts: this._opts.profilerOpts,
131
+ })
132
+ }
133
+
134
+ /**
135
+ * Return a compact error string representation of the object
136
+ */
137
+ errorStr() {
138
+ let hf = ''
139
+ try {
140
+ hf = this.common.hardfork()
141
+ } catch {
142
+ hf = 'error'
143
+ }
144
+ const errorStr = `vm hf=${hf}`
145
+ return errorStr
146
+ }
147
+ }