jaelis-node 1.10.0 → 2.1.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.
- package/README.md +156 -439
- package/bin/jaelis-node.js +83 -504
- package/lib/index.js +31 -2840
- package/lib/node.js +309 -0
- package/lib/rpc.js +315 -0
- package/lib/storage.js +198 -0
- package/lib/sync.js +366 -0
- package/package.json +19 -53
- package/config/default.json +0 -74
- package/config/mainnet.json +0 -30
- package/config/testnet.json +0 -26
- package/lib/JAELIS-VM/lib/adapters/evm-adapter.js +0 -454
- package/lib/JAELIS-VM/lib/adapters/index.js +0 -411
- package/lib/JAELIS-VM/lib/adapters/svm-adapter.js +0 -457
- package/lib/JAELIS-VM/lib/compiler/jir-compiler.js +0 -1097
- package/lib/JAELIS-VM/lib/execution/engine.js +0 -1183
- package/lib/JAELIS-VM/lib/index.js +0 -440
- package/lib/JAELIS-VM/lib/integration/jaelis-integration.js +0 -543
- package/lib/JAELIS-VM/lib/serialization/serializer.js +0 -819
- package/lib/JAELIS-VM/lib/state/state-manager.js +0 -1116
- package/lib/JAELIS-VM/lib/translator/bytecode-translator.js +0 -1222
- package/lib/JAELIS-VM/lib/unified/cross-chain-deploy.js +0 -1678
- package/lib/JAELIS-VM/lib/unified/cross-chain-state.js +0 -836
- package/lib/JAELIS-VM/lib/unified/dynamic-contracts.js +0 -1127
- package/lib/JAELIS-VM/lib/unified/index.js +0 -456
- package/lib/JAELIS-VM/lib/unified/jaelis-abi.js +0 -1150
- package/lib/JAELIS-VM/lib/unified/unified-compiler.js +0 -1350
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/download-cbor-prebuilds.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/download-msgpackr-prebuilds.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-optional.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test +0 -12
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages-test.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/.bin/node-gyp-build-optional-packages.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/.package-lock.json +0 -127
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/README.md +0 -1
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/index.js +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/node.abi115.node +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/node.napi.node +0 -0
- package/lib/JAELIS-VM/node_modules/@cbor-extract/cbor-extract-win32-x64/package.json +0 -17
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/README.md +0 -1
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/index.js +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/node.abi115.node +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/node.napi.node +0 -0
- package/lib/JAELIS-VM/node_modules/@msgpackr-extract/msgpackr-extract-win32-x64/package.json +0 -17
- package/lib/JAELIS-VM/node_modules/cbor-extract/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/cbor-extract/README.md +0 -5
- package/lib/JAELIS-VM/node_modules/cbor-extract/bin/download-prebuilds.js +0 -11
- package/lib/JAELIS-VM/node_modules/cbor-extract/binding.gyp +0 -60
- package/lib/JAELIS-VM/node_modules/cbor-extract/index.js +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-extract/package.json +0 -50
- package/lib/JAELIS-VM/node_modules/cbor-extract/src/extract.cpp +0 -198
- package/lib/JAELIS-VM/node_modules/cbor-x/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/cbor-x/README.md +0 -380
- package/lib/JAELIS-VM/node_modules/cbor-x/SECURITY.md +0 -11
- package/lib/JAELIS-VM/node_modules/cbor-x/benchmark.md +0 -73
- package/lib/JAELIS-VM/node_modules/cbor-x/browser.js +0 -11
- package/lib/JAELIS-VM/node_modules/cbor-x/decode.d.ts +0 -2
- package/lib/JAELIS-VM/node_modules/cbor-x/decode.js +0 -1300
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/decode-no-eval.cjs +0 -1244
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/decode-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.cjs +0 -2509
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index-no-eval.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.js +0 -2508
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/index.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/node.cjs +0 -2629
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/node.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/test.js +0 -3343
- package/lib/JAELIS-VM/node_modules/cbor-x/dist/test.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/encode.d.ts +0 -1
- package/lib/JAELIS-VM/node_modules/cbor-x/encode.js +0 -1231
- package/lib/JAELIS-VM/node_modules/cbor-x/index.d.ts +0 -79
- package/lib/JAELIS-VM/node_modules/cbor-x/index.js +0 -3
- package/lib/JAELIS-VM/node_modules/cbor-x/iterators.js +0 -85
- package/lib/JAELIS-VM/node_modules/cbor-x/node-index.js +0 -24
- package/lib/JAELIS-VM/node_modules/cbor-x/package.json +0 -94
- package/lib/JAELIS-VM/node_modules/cbor-x/rollup.config.js +0 -88
- package/lib/JAELIS-VM/node_modules/cbor-x/stream.js +0 -61
- package/lib/JAELIS-VM/node_modules/cbor-x/webpack.config.js +0 -19
- package/lib/JAELIS-VM/node_modules/detect-libc/LICENSE +0 -201
- package/lib/JAELIS-VM/node_modules/detect-libc/README.md +0 -163
- package/lib/JAELIS-VM/node_modules/detect-libc/index.d.ts +0 -14
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/detect-libc.js +0 -313
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/elf.js +0 -39
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/filesystem.js +0 -51
- package/lib/JAELIS-VM/node_modules/detect-libc/lib/process.js +0 -24
- package/lib/JAELIS-VM/node_modules/detect-libc/package.json +0 -44
- package/lib/JAELIS-VM/node_modules/msgpackr/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/msgpackr/README.md +0 -372
- package/lib/JAELIS-VM/node_modules/msgpackr/SECURITY.md +0 -11
- package/lib/JAELIS-VM/node_modules/msgpackr/benchmark.md +0 -67
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.cjs +0 -2407
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index-no-eval.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.js +0 -2406
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.min.js +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/index.min.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/node.cjs +0 -3320
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/node.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/test.js +0 -4540
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/test.js.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/unpack-no-eval.cjs +0 -1250
- package/lib/JAELIS-VM/node_modules/msgpackr/dist/unpack-no-eval.cjs.map +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/index.d.cts +0 -91
- package/lib/JAELIS-VM/node_modules/msgpackr/index.d.ts +0 -91
- package/lib/JAELIS-VM/node_modules/msgpackr/index.js +0 -5
- package/lib/JAELIS-VM/node_modules/msgpackr/iterators.js +0 -87
- package/lib/JAELIS-VM/node_modules/msgpackr/node-index.js +0 -25
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.d.cts +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.d.ts +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr/pack.js +0 -1141
- package/lib/JAELIS-VM/node_modules/msgpackr/package.json +0 -104
- package/lib/JAELIS-VM/node_modules/msgpackr/rollup.config.js +0 -88
- package/lib/JAELIS-VM/node_modules/msgpackr/stream.js +0 -57
- package/lib/JAELIS-VM/node_modules/msgpackr/struct.js +0 -815
- package/lib/JAELIS-VM/node_modules/msgpackr/test-worker.js +0 -3
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.d.cts +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.d.ts +0 -2
- package/lib/JAELIS-VM/node_modules/msgpackr/unpack.js +0 -1221
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/README.md +0 -5
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/bin/download-prebuilds.js +0 -13
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/binding.gyp +0 -63
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/index.js +0 -1
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages +0 -12
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional +0 -12
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-optional.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test +0 -12
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages-test.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages.cmd +0 -17
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/.bin/node-gyp-build-optional-packages.ps1 +0 -28
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/README.md +0 -58
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/bin.js +0 -82
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/build-test.js +0 -19
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/index.js +0 -6
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/node-gyp-build.js +0 -236
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/optional.js +0 -7
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/node_modules/node-gyp-build-optional-packages/package.json +0 -32
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/package.json +0 -50
- package/lib/JAELIS-VM/node_modules/msgpackr-extract/src/extract.cpp +0 -274
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/LICENSE +0 -21
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/README.md +0 -58
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/bin.js +0 -77
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/build-test.js +0 -19
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/index.js +0 -224
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/optional.js +0 -7
- package/lib/JAELIS-VM/node_modules/node-gyp-build-optional-packages/package.json +0 -32
- package/lib/JAELIS-VM/package-lock.json +0 -284
- package/lib/JAELIS-VM/package.json +0 -38
- package/lib/JAELIS-VM/test/comprehensive.test.js +0 -267
- package/lib/JAELIS-VM/test/cross-chain-test.js +0 -470
- package/lib/JAELIS-VM/test/unified-vm-test.js +0 -459
- package/lib/JAELIS-VM/test/unified.test.js +0 -166
- package/lib/JAELIS-VM/test/vm.test.js +0 -599
- package/lib/settlement-server.js +0 -999
- package/lib/vm/index.js +0 -397
|
@@ -1,1183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JAELIS EXECUTION ENGINE
|
|
3
|
-
*
|
|
4
|
-
* Executes JIR bytecode using multiple execution strategies:
|
|
5
|
-
* - Interpreter: Development/debugging (baseline)
|
|
6
|
-
* - AOT Compiler: Production (10x faster)
|
|
7
|
-
* - JIT Compiler: Hot path optimization
|
|
8
|
-
*
|
|
9
|
-
* Features:
|
|
10
|
-
* - WASM 3.0 compatible (64-bit, GC, threads)
|
|
11
|
-
* - Deterministic execution
|
|
12
|
-
* - Gas/Lode metering
|
|
13
|
-
* - Cross-VM state access
|
|
14
|
-
*
|
|
15
|
-
* @version 0.1.0
|
|
16
|
-
* @author Mario Papaleo - JAELIS Foundation
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const EventEmitter = require('events');
|
|
20
|
-
const crypto = require('crypto');
|
|
21
|
-
|
|
22
|
-
// Import opcodes from compiler
|
|
23
|
-
const JIR_OPCODES = {
|
|
24
|
-
NOP: 0x00, BLOCK: 0x01, LOOP: 0x02, IF: 0x03, ELSE: 0x04, END: 0x05,
|
|
25
|
-
BR: 0x06, BR_IF: 0x07, RETURN: 0x08, CALL: 0x09, CALL_INDIRECT: 0x0A,
|
|
26
|
-
DROP: 0x10, SELECT: 0x11, LOCAL_GET: 0x12, LOCAL_SET: 0x13, LOCAL_TEE: 0x14,
|
|
27
|
-
GLOBAL_GET: 0x15, GLOBAL_SET: 0x16,
|
|
28
|
-
I32_LOAD: 0x20, I64_LOAD: 0x21, F32_LOAD: 0x22, F64_LOAD: 0x23,
|
|
29
|
-
I32_STORE: 0x24, I64_STORE: 0x25, F32_STORE: 0x26, F64_STORE: 0x27,
|
|
30
|
-
MEMORY_SIZE: 0x28, MEMORY_GROW: 0x29, MEMORY_COPY: 0x2A, MEMORY_FILL: 0x2B,
|
|
31
|
-
I32_CONST: 0x30, I64_CONST: 0x31, F32_CONST: 0x32, F64_CONST: 0x33,
|
|
32
|
-
I32_ADD: 0x34, I32_SUB: 0x35, I32_MUL: 0x36, I32_DIV_S: 0x37, I32_DIV_U: 0x38,
|
|
33
|
-
I64_ADD: 0x39, I64_SUB: 0x3A, I64_MUL: 0x3B, I64_DIV_S: 0x3C, I64_DIV_U: 0x3D,
|
|
34
|
-
I32_EQ: 0x40, I32_NE: 0x41, I32_LT_S: 0x42, I32_LT_U: 0x43,
|
|
35
|
-
I32_GT_S: 0x44, I32_GT_U: 0x45, I32_LE_S: 0x46, I32_LE_U: 0x47,
|
|
36
|
-
I32_GE_S: 0x48, I32_GE_U: 0x49, I64_EQ: 0x4A, I64_NE: 0x4B,
|
|
37
|
-
I32_AND: 0x50, I32_OR: 0x51, I32_XOR: 0x52, I32_SHL: 0x53,
|
|
38
|
-
I32_SHR_S: 0x54, I32_SHR_U: 0x55, I64_AND: 0x56, I64_OR: 0x57, I64_XOR: 0x58,
|
|
39
|
-
REF_NULL: 0x60, REF_IS_NULL: 0x61, REF_FUNC: 0x62,
|
|
40
|
-
STRUCT_NEW: 0x63, STRUCT_GET: 0x64, STRUCT_SET: 0x65,
|
|
41
|
-
ARRAY_NEW: 0x66, ARRAY_GET: 0x67, ARRAY_SET: 0x68, ARRAY_LEN: 0x69,
|
|
42
|
-
ATOMIC_LOAD: 0x70, ATOMIC_STORE: 0x71, ATOMIC_ADD: 0x72, ATOMIC_SUB: 0x73,
|
|
43
|
-
ATOMIC_AND: 0x74, ATOMIC_OR: 0x75, ATOMIC_XOR: 0x76, ATOMIC_CMPXCHG: 0x77,
|
|
44
|
-
ATOMIC_WAIT: 0x78, ATOMIC_NOTIFY: 0x79,
|
|
45
|
-
SLOAD: 0x80, SSTORE: 0x81, SLOAD_EXT: 0x82, SSTORE_EXT: 0x83,
|
|
46
|
-
BALANCE: 0x84, TRANSFER: 0x85, TRANSFER_TOKEN: 0x86,
|
|
47
|
-
CONTRACT_CALL: 0x87, DELEGATE_CALL: 0x88, STATIC_CALL: 0x89,
|
|
48
|
-
CREATE: 0x8A, CREATE2: 0x8B, SELFDESTRUCT: 0x8C,
|
|
49
|
-
CALLER: 0x90, ORIGIN: 0x91, CALLVALUE: 0x92, CALLDATA: 0x93,
|
|
50
|
-
CALLDATASIZE: 0x94, RETURNDATASIZE: 0x95, RETURNDATACOPY: 0x96,
|
|
51
|
-
BLOCKHASH: 0xA0, COINBASE: 0xA1, TIMESTAMP: 0xA2, BLOCKNUMBER: 0xA3,
|
|
52
|
-
DIFFICULTY: 0xA4, GASLIMIT: 0xA5, CHAINID: 0xA6, SELFBALANCE: 0xA7, BASEFEE: 0xA8,
|
|
53
|
-
SHA256: 0xB0, KECCAK256: 0xB1, BLAKE2B: 0xB2, BLAKE3: 0xB3,
|
|
54
|
-
POSEIDON: 0xB4, ECRECOVER: 0xB5, ECADD: 0xB6, ECMUL: 0xB7,
|
|
55
|
-
ECPAIRING: 0xB8, ED25519_VERIFY: 0xB9,
|
|
56
|
-
LOG0: 0xC0, LOG1: 0xC1, LOG2: 0xC2, LOG3: 0xC3, LOG4: 0xC4,
|
|
57
|
-
CROSS_VM_CALL: 0xD0, CROSS_VM_TRANSFER: 0xD1, CROSS_VM_STATE: 0xD2,
|
|
58
|
-
BRIDGE_LOCK: 0xD3, BRIDGE_UNLOCK: 0xD4, BRIDGE_MINT: 0xD5, BRIDGE_BURN: 0xD6,
|
|
59
|
-
GAS: 0xE0, LODE_SIGNAL: 0xE1, METER_START: 0xE2, METER_END: 0xE3,
|
|
60
|
-
DEBUG_PRINT: 0xF0, DEBUG_BREAK: 0xF1, DEBUG_TRACE: 0xF2,
|
|
61
|
-
REVERT: 0xFE, HALT: 0xFF
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// Gas costs for each opcode (for metering)
|
|
65
|
-
const GAS_COSTS = {
|
|
66
|
-
[JIR_OPCODES.NOP]: 1,
|
|
67
|
-
[JIR_OPCODES.I32_ADD]: 3,
|
|
68
|
-
[JIR_OPCODES.I32_SUB]: 3,
|
|
69
|
-
[JIR_OPCODES.I32_MUL]: 5,
|
|
70
|
-
[JIR_OPCODES.I32_DIV_S]: 8,
|
|
71
|
-
[JIR_OPCODES.I64_ADD]: 3,
|
|
72
|
-
[JIR_OPCODES.I64_SUB]: 3,
|
|
73
|
-
[JIR_OPCODES.I64_MUL]: 5,
|
|
74
|
-
[JIR_OPCODES.I64_DIV_S]: 8,
|
|
75
|
-
[JIR_OPCODES.SLOAD]: 100,
|
|
76
|
-
[JIR_OPCODES.SSTORE]: 20000,
|
|
77
|
-
[JIR_OPCODES.CONTRACT_CALL]: 700,
|
|
78
|
-
[JIR_OPCODES.CREATE]: 32000,
|
|
79
|
-
[JIR_OPCODES.CREATE2]: 32000,
|
|
80
|
-
[JIR_OPCODES.KECCAK256]: 30,
|
|
81
|
-
[JIR_OPCODES.SHA256]: 60,
|
|
82
|
-
[JIR_OPCODES.TRANSFER]: 2100,
|
|
83
|
-
[JIR_OPCODES.LOG0]: 375,
|
|
84
|
-
[JIR_OPCODES.LOG1]: 750,
|
|
85
|
-
[JIR_OPCODES.LOG2]: 1125,
|
|
86
|
-
[JIR_OPCODES.CROSS_VM_CALL]: 5000,
|
|
87
|
-
default: 3
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Stack Frame for execution
|
|
92
|
-
*/
|
|
93
|
-
class StackFrame {
|
|
94
|
-
constructor(functionIndex, returnPC, locals = []) {
|
|
95
|
-
this.functionIndex = functionIndex;
|
|
96
|
-
this.returnPC = returnPC;
|
|
97
|
-
this.locals = locals;
|
|
98
|
-
this.operandStack = [];
|
|
99
|
-
this.blockStack = []; // For structured control flow
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
push(value) {
|
|
103
|
-
this.operandStack.push(value);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
pop() {
|
|
107
|
-
if (this.operandStack.length === 0) {
|
|
108
|
-
throw new Error('Stack underflow');
|
|
109
|
-
}
|
|
110
|
-
return this.operandStack.pop();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
peek() {
|
|
114
|
-
return this.operandStack[this.operandStack.length - 1];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
getLocal(index) {
|
|
118
|
-
return this.locals[index];
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
setLocal(index, value) {
|
|
122
|
-
this.locals[index] = value;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* JAELIS Execution Engine
|
|
128
|
-
*
|
|
129
|
-
* Supports three execution modes:
|
|
130
|
-
* 1. Interpreter - Step-by-step execution (good for debugging)
|
|
131
|
-
* 2. AOT - Ahead-of-time compilation (fastest for production)
|
|
132
|
-
* 3. JIT - Just-in-time compilation (optimizes hot paths)
|
|
133
|
-
*/
|
|
134
|
-
class ExecutionEngine extends EventEmitter {
|
|
135
|
-
constructor(config = {}) {
|
|
136
|
-
super();
|
|
137
|
-
|
|
138
|
-
this.config = {
|
|
139
|
-
executionMode: config.executionMode || 'interpreter',
|
|
140
|
-
maxMemory: config.maxMemory || 1024 * 1024 * 1024, // 1GB
|
|
141
|
-
maxStack: config.maxStack || 1024 * 1024 * 64, // 64MB
|
|
142
|
-
maxHeap: config.maxHeap || 1024 * 1024 * 512, // 512MB
|
|
143
|
-
maxInstructions: config.maxInstructions || 100000000, // 100M
|
|
144
|
-
meteringEnabled: config.meteringEnabled !== false,
|
|
145
|
-
debug: config.debug || false,
|
|
146
|
-
trace: config.trace || false,
|
|
147
|
-
...config
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
// Memory (64-bit addressable!)
|
|
151
|
-
this.memory = null;
|
|
152
|
-
this.memorySize = 0;
|
|
153
|
-
|
|
154
|
-
// Heap for GC-managed objects
|
|
155
|
-
this.heap = new Map();
|
|
156
|
-
this.heapNextId = 1;
|
|
157
|
-
|
|
158
|
-
// Globals
|
|
159
|
-
this.globals = new Map();
|
|
160
|
-
|
|
161
|
-
// Tables (function references)
|
|
162
|
-
this.tables = [];
|
|
163
|
-
|
|
164
|
-
// Call stack
|
|
165
|
-
this.callStack = [];
|
|
166
|
-
|
|
167
|
-
// Execution state
|
|
168
|
-
this.pc = 0; // Program counter
|
|
169
|
-
this.running = false;
|
|
170
|
-
this.halted = false;
|
|
171
|
-
|
|
172
|
-
// Metering
|
|
173
|
-
this.instructionsExecuted = 0;
|
|
174
|
-
this.gasUsed = 0;
|
|
175
|
-
this.gasLimit = 0;
|
|
176
|
-
|
|
177
|
-
// Execution context (blockchain-specific)
|
|
178
|
-
this.context = null;
|
|
179
|
-
|
|
180
|
-
// State changes for rollback
|
|
181
|
-
this.stateChanges = [];
|
|
182
|
-
this.logs = [];
|
|
183
|
-
|
|
184
|
-
// AOT compiled functions cache
|
|
185
|
-
this.aotCache = new Map();
|
|
186
|
-
|
|
187
|
-
// JIT hot path detection
|
|
188
|
-
this.jitStats = new Map();
|
|
189
|
-
this.jitThreshold = 100; // Compile after 100 calls
|
|
190
|
-
|
|
191
|
-
// Host functions (blockchain operations)
|
|
192
|
-
this.hostFunctions = new Map();
|
|
193
|
-
this._registerHostFunctions();
|
|
194
|
-
|
|
195
|
-
console.log(`[Engine] Initialized in ${this.config.executionMode.toUpperCase()} mode`);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Execute a JIR module
|
|
200
|
-
*
|
|
201
|
-
* @param {object} jir - Compiled JIR module
|
|
202
|
-
* @param {string} functionName - Function to execute
|
|
203
|
-
* @param {Buffer} args - Serialized arguments
|
|
204
|
-
* @param {object} context - Execution context
|
|
205
|
-
* @returns {object} Execution result
|
|
206
|
-
*/
|
|
207
|
-
async execute(jir, functionName, args, context = {}) {
|
|
208
|
-
const startTime = Date.now();
|
|
209
|
-
|
|
210
|
-
// Reset state
|
|
211
|
-
this._reset();
|
|
212
|
-
|
|
213
|
-
// Setup context
|
|
214
|
-
this.context = {
|
|
215
|
-
caller: context.caller || '0x0000000000000000000000000000000000000000',
|
|
216
|
-
origin: context.origin || context.caller || '0x0000000000000000000000000000000000000000',
|
|
217
|
-
value: BigInt(context.value || 0),
|
|
218
|
-
gasLimit: context.gasLimit || this.config.maxInstructions,
|
|
219
|
-
blockNumber: context.blockNumber || 0,
|
|
220
|
-
timestamp: context.timestamp || Math.floor(Date.now() / 1000),
|
|
221
|
-
chainId: context.chainId || 4545,
|
|
222
|
-
address: context.address || '0x0000000000000000000000000000000000000000',
|
|
223
|
-
...context
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
this.gasLimit = this.context.gasLimit;
|
|
227
|
-
|
|
228
|
-
// Initialize memory
|
|
229
|
-
this._initMemory(jir.memory);
|
|
230
|
-
|
|
231
|
-
// Load globals
|
|
232
|
-
this._loadGlobals(jir.globals);
|
|
233
|
-
|
|
234
|
-
// Load data sections
|
|
235
|
-
this._loadData(jir.data);
|
|
236
|
-
|
|
237
|
-
// Find function
|
|
238
|
-
const funcIndex = jir.exports.findIndex(e => e.name === functionName && e.kind === 'function');
|
|
239
|
-
if (funcIndex === -1) {
|
|
240
|
-
throw new Error(`Function not found: ${functionName}`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const func = jir.functions[jir.exports[funcIndex].index];
|
|
244
|
-
if (!func) {
|
|
245
|
-
throw new Error(`Function index out of bounds: ${jir.exports[funcIndex].index}`);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Prepare arguments
|
|
249
|
-
const parsedArgs = this._parseArguments(args, func.params);
|
|
250
|
-
|
|
251
|
-
// Execute based on mode
|
|
252
|
-
let result;
|
|
253
|
-
switch (this.config.executionMode) {
|
|
254
|
-
case 'aot':
|
|
255
|
-
result = await this._executeAOT(jir, func, parsedArgs);
|
|
256
|
-
break;
|
|
257
|
-
case 'jit':
|
|
258
|
-
result = await this._executeJIT(jir, func, parsedArgs);
|
|
259
|
-
break;
|
|
260
|
-
case 'interpreter':
|
|
261
|
-
default:
|
|
262
|
-
result = await this._executeInterpreter(jir, func, parsedArgs);
|
|
263
|
-
break;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const executionTime = Date.now() - startTime;
|
|
267
|
-
|
|
268
|
-
return {
|
|
269
|
-
success: !this.halted || result.success !== false,
|
|
270
|
-
returnData: result.returnData || Buffer.alloc(0),
|
|
271
|
-
instructionsUsed: this.instructionsExecuted,
|
|
272
|
-
gasUsed: this.gasUsed,
|
|
273
|
-
executionTime,
|
|
274
|
-
logs: this.logs,
|
|
275
|
-
stateChanges: this.stateChanges
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// ═══════════════════════════════════════════════════════════════
|
|
280
|
-
// INTERPRETER MODE
|
|
281
|
-
// ═══════════════════════════════════════════════════════════════
|
|
282
|
-
|
|
283
|
-
async _executeInterpreter(jir, func, args) {
|
|
284
|
-
if (this.config.debug) {
|
|
285
|
-
console.log(`[Engine] Interpreting function: ${func.name}`);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Create initial stack frame
|
|
289
|
-
const frame = new StackFrame(0, -1, [...args]);
|
|
290
|
-
this.callStack.push(frame);
|
|
291
|
-
|
|
292
|
-
// Get bytecode
|
|
293
|
-
const bytecode = jir.bytecode;
|
|
294
|
-
this.pc = this._findFunctionOffset(jir, func);
|
|
295
|
-
|
|
296
|
-
this.running = true;
|
|
297
|
-
|
|
298
|
-
while (this.running && !this.halted) {
|
|
299
|
-
// Check limits
|
|
300
|
-
if (this.config.meteringEnabled && this.instructionsExecuted >= this.gasLimit) {
|
|
301
|
-
throw new Error('Out of gas');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (this.pc >= bytecode.length) {
|
|
305
|
-
break;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const opcode = bytecode[this.pc];
|
|
309
|
-
|
|
310
|
-
// Trace execution
|
|
311
|
-
if (this.config.trace) {
|
|
312
|
-
console.log(`[Trace] PC=${this.pc} OP=0x${opcode.toString(16)} Stack=${frame.operandStack.length}`);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Execute opcode
|
|
316
|
-
await this._executeOpcode(opcode, bytecode, jir);
|
|
317
|
-
|
|
318
|
-
// Update metrics
|
|
319
|
-
this.instructionsExecuted++;
|
|
320
|
-
this.gasUsed += GAS_COSTS[opcode] || GAS_COSTS.default;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Get return value
|
|
324
|
-
const returnValue = frame.operandStack.length > 0 ? frame.pop() : null;
|
|
325
|
-
|
|
326
|
-
return {
|
|
327
|
-
success: !this.halted,
|
|
328
|
-
returnData: this._serializeReturn(returnValue)
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
async _executeOpcode(opcode, bytecode, jir) {
|
|
333
|
-
const frame = this.callStack[this.callStack.length - 1];
|
|
334
|
-
|
|
335
|
-
switch (opcode) {
|
|
336
|
-
// ═══════════════════════════════════════════════════════════════
|
|
337
|
-
// CONTROL FLOW
|
|
338
|
-
// ═══════════════════════════════════════════════════════════════
|
|
339
|
-
|
|
340
|
-
case JIR_OPCODES.NOP:
|
|
341
|
-
this.pc++;
|
|
342
|
-
break;
|
|
343
|
-
|
|
344
|
-
case JIR_OPCODES.BLOCK:
|
|
345
|
-
frame.blockStack.push({ type: 'block', pc: this.pc });
|
|
346
|
-
this.pc++;
|
|
347
|
-
break;
|
|
348
|
-
|
|
349
|
-
case JIR_OPCODES.LOOP:
|
|
350
|
-
frame.blockStack.push({ type: 'loop', pc: this.pc });
|
|
351
|
-
this.pc++;
|
|
352
|
-
break;
|
|
353
|
-
|
|
354
|
-
case JIR_OPCODES.IF:
|
|
355
|
-
const condition = frame.pop();
|
|
356
|
-
if (condition) {
|
|
357
|
-
frame.blockStack.push({ type: 'if', pc: this.pc });
|
|
358
|
-
this.pc++;
|
|
359
|
-
} else {
|
|
360
|
-
// Jump to else or end
|
|
361
|
-
this.pc = this._findElseOrEnd(bytecode, this.pc);
|
|
362
|
-
}
|
|
363
|
-
break;
|
|
364
|
-
|
|
365
|
-
case JIR_OPCODES.ELSE:
|
|
366
|
-
// Skip to end
|
|
367
|
-
this.pc = this._findEnd(bytecode, this.pc);
|
|
368
|
-
break;
|
|
369
|
-
|
|
370
|
-
case JIR_OPCODES.END:
|
|
371
|
-
if (frame.blockStack.length > 0) {
|
|
372
|
-
frame.blockStack.pop();
|
|
373
|
-
}
|
|
374
|
-
this.pc++;
|
|
375
|
-
break;
|
|
376
|
-
|
|
377
|
-
case JIR_OPCODES.BR:
|
|
378
|
-
const depth1 = bytecode[++this.pc];
|
|
379
|
-
this._branch(depth1, frame);
|
|
380
|
-
break;
|
|
381
|
-
|
|
382
|
-
case JIR_OPCODES.BR_IF:
|
|
383
|
-
const depth2 = bytecode[++this.pc];
|
|
384
|
-
if (frame.pop()) {
|
|
385
|
-
this._branch(depth2, frame);
|
|
386
|
-
} else {
|
|
387
|
-
this.pc++;
|
|
388
|
-
}
|
|
389
|
-
break;
|
|
390
|
-
|
|
391
|
-
case JIR_OPCODES.RETURN:
|
|
392
|
-
if (this.callStack.length <= 1) {
|
|
393
|
-
this.running = false;
|
|
394
|
-
} else {
|
|
395
|
-
const returnValue = frame.operandStack.length > 0 ? frame.pop() : null;
|
|
396
|
-
this.callStack.pop();
|
|
397
|
-
const parentFrame = this.callStack[this.callStack.length - 1];
|
|
398
|
-
if (returnValue !== null) {
|
|
399
|
-
parentFrame.push(returnValue);
|
|
400
|
-
}
|
|
401
|
-
this.pc = frame.returnPC;
|
|
402
|
-
}
|
|
403
|
-
break;
|
|
404
|
-
|
|
405
|
-
case JIR_OPCODES.CALL:
|
|
406
|
-
const funcIdx = bytecode[++this.pc];
|
|
407
|
-
await this._call(funcIdx, jir);
|
|
408
|
-
break;
|
|
409
|
-
|
|
410
|
-
case JIR_OPCODES.CALL_INDIRECT:
|
|
411
|
-
const tableIdx = bytecode[++this.pc];
|
|
412
|
-
const funcTypeIdx = bytecode[++this.pc];
|
|
413
|
-
const funcRef = frame.pop();
|
|
414
|
-
await this._callIndirect(tableIdx, funcTypeIdx, funcRef, jir);
|
|
415
|
-
break;
|
|
416
|
-
|
|
417
|
-
// ═══════════════════════════════════════════════════════════════
|
|
418
|
-
// STACK OPERATIONS
|
|
419
|
-
// ═══════════════════════════════════════════════════════════════
|
|
420
|
-
|
|
421
|
-
case JIR_OPCODES.DROP:
|
|
422
|
-
frame.pop();
|
|
423
|
-
this.pc++;
|
|
424
|
-
break;
|
|
425
|
-
|
|
426
|
-
case JIR_OPCODES.SELECT:
|
|
427
|
-
const cond = frame.pop();
|
|
428
|
-
const val2 = frame.pop();
|
|
429
|
-
const val1 = frame.pop();
|
|
430
|
-
frame.push(cond ? val1 : val2);
|
|
431
|
-
this.pc++;
|
|
432
|
-
break;
|
|
433
|
-
|
|
434
|
-
case JIR_OPCODES.LOCAL_GET:
|
|
435
|
-
const localIdx1 = bytecode[++this.pc];
|
|
436
|
-
frame.push(frame.getLocal(localIdx1));
|
|
437
|
-
this.pc++;
|
|
438
|
-
break;
|
|
439
|
-
|
|
440
|
-
case JIR_OPCODES.LOCAL_SET:
|
|
441
|
-
const localIdx2 = bytecode[++this.pc];
|
|
442
|
-
frame.setLocal(localIdx2, frame.pop());
|
|
443
|
-
this.pc++;
|
|
444
|
-
break;
|
|
445
|
-
|
|
446
|
-
case JIR_OPCODES.LOCAL_TEE:
|
|
447
|
-
const localIdx3 = bytecode[++this.pc];
|
|
448
|
-
frame.setLocal(localIdx3, frame.peek());
|
|
449
|
-
this.pc++;
|
|
450
|
-
break;
|
|
451
|
-
|
|
452
|
-
case JIR_OPCODES.GLOBAL_GET:
|
|
453
|
-
const globalIdx1 = bytecode[++this.pc];
|
|
454
|
-
frame.push(this.globals.get(globalIdx1) || 0);
|
|
455
|
-
this.pc++;
|
|
456
|
-
break;
|
|
457
|
-
|
|
458
|
-
case JIR_OPCODES.GLOBAL_SET:
|
|
459
|
-
const globalIdx2 = bytecode[++this.pc];
|
|
460
|
-
this.globals.set(globalIdx2, frame.pop());
|
|
461
|
-
this.pc++;
|
|
462
|
-
break;
|
|
463
|
-
|
|
464
|
-
// ═══════════════════════════════════════════════════════════════
|
|
465
|
-
// MEMORY OPERATIONS (64-bit addressing)
|
|
466
|
-
// ═══════════════════════════════════════════════════════════════
|
|
467
|
-
|
|
468
|
-
case JIR_OPCODES.I32_LOAD:
|
|
469
|
-
const addr1 = Number(frame.pop());
|
|
470
|
-
frame.push(this.memory.readInt32LE(addr1));
|
|
471
|
-
this.pc++;
|
|
472
|
-
break;
|
|
473
|
-
|
|
474
|
-
case JIR_OPCODES.I64_LOAD:
|
|
475
|
-
const addr2 = Number(frame.pop());
|
|
476
|
-
frame.push(this.memory.readBigInt64LE(addr2));
|
|
477
|
-
this.pc++;
|
|
478
|
-
break;
|
|
479
|
-
|
|
480
|
-
case JIR_OPCODES.I32_STORE:
|
|
481
|
-
const val_store1 = frame.pop();
|
|
482
|
-
const addr_store1 = Number(frame.pop());
|
|
483
|
-
this.memory.writeInt32LE(val_store1, addr_store1);
|
|
484
|
-
this.pc++;
|
|
485
|
-
break;
|
|
486
|
-
|
|
487
|
-
case JIR_OPCODES.I64_STORE:
|
|
488
|
-
const val_store2 = frame.pop();
|
|
489
|
-
const addr_store2 = Number(frame.pop());
|
|
490
|
-
this.memory.writeBigInt64LE(BigInt(val_store2), addr_store2);
|
|
491
|
-
this.pc++;
|
|
492
|
-
break;
|
|
493
|
-
|
|
494
|
-
case JIR_OPCODES.MEMORY_SIZE:
|
|
495
|
-
frame.push(Math.floor(this.memorySize / 65536)); // Return in pages
|
|
496
|
-
this.pc++;
|
|
497
|
-
break;
|
|
498
|
-
|
|
499
|
-
case JIR_OPCODES.MEMORY_GROW:
|
|
500
|
-
const pages = frame.pop();
|
|
501
|
-
const oldSize = Math.floor(this.memorySize / 65536);
|
|
502
|
-
const newSize = this.memorySize + (pages * 65536);
|
|
503
|
-
if (newSize <= this.config.maxMemory) {
|
|
504
|
-
const newMemory = Buffer.alloc(newSize);
|
|
505
|
-
this.memory.copy(newMemory);
|
|
506
|
-
this.memory = newMemory;
|
|
507
|
-
this.memorySize = newSize;
|
|
508
|
-
frame.push(oldSize);
|
|
509
|
-
} else {
|
|
510
|
-
frame.push(-1); // Failed
|
|
511
|
-
}
|
|
512
|
-
this.pc++;
|
|
513
|
-
break;
|
|
514
|
-
|
|
515
|
-
// ═══════════════════════════════════════════════════════════════
|
|
516
|
-
// NUMERIC OPERATIONS
|
|
517
|
-
// ═══════════════════════════════════════════════════════════════
|
|
518
|
-
|
|
519
|
-
case JIR_OPCODES.I32_CONST:
|
|
520
|
-
const i32val = bytecode.readInt32LE(++this.pc);
|
|
521
|
-
frame.push(i32val);
|
|
522
|
-
this.pc += 4;
|
|
523
|
-
break;
|
|
524
|
-
|
|
525
|
-
case JIR_OPCODES.I64_CONST:
|
|
526
|
-
const i64val = bytecode.readBigInt64LE(++this.pc);
|
|
527
|
-
frame.push(i64val);
|
|
528
|
-
this.pc += 8;
|
|
529
|
-
break;
|
|
530
|
-
|
|
531
|
-
case JIR_OPCODES.I32_ADD:
|
|
532
|
-
frame.push((frame.pop() + frame.pop()) | 0);
|
|
533
|
-
this.pc++;
|
|
534
|
-
break;
|
|
535
|
-
|
|
536
|
-
case JIR_OPCODES.I32_SUB:
|
|
537
|
-
const sub2 = frame.pop();
|
|
538
|
-
const sub1 = frame.pop();
|
|
539
|
-
frame.push((sub1 - sub2) | 0);
|
|
540
|
-
this.pc++;
|
|
541
|
-
break;
|
|
542
|
-
|
|
543
|
-
case JIR_OPCODES.I32_MUL:
|
|
544
|
-
frame.push(Math.imul(frame.pop(), frame.pop()));
|
|
545
|
-
this.pc++;
|
|
546
|
-
break;
|
|
547
|
-
|
|
548
|
-
case JIR_OPCODES.I32_DIV_S:
|
|
549
|
-
const div2 = frame.pop();
|
|
550
|
-
const div1 = frame.pop();
|
|
551
|
-
if (div2 === 0) throw new Error('Division by zero');
|
|
552
|
-
frame.push((div1 / div2) | 0);
|
|
553
|
-
this.pc++;
|
|
554
|
-
break;
|
|
555
|
-
|
|
556
|
-
case JIR_OPCODES.I64_ADD:
|
|
557
|
-
frame.push(BigInt(frame.pop()) + BigInt(frame.pop()));
|
|
558
|
-
this.pc++;
|
|
559
|
-
break;
|
|
560
|
-
|
|
561
|
-
case JIR_OPCODES.I64_SUB:
|
|
562
|
-
const lsub2 = BigInt(frame.pop());
|
|
563
|
-
const lsub1 = BigInt(frame.pop());
|
|
564
|
-
frame.push(lsub1 - lsub2);
|
|
565
|
-
this.pc++;
|
|
566
|
-
break;
|
|
567
|
-
|
|
568
|
-
case JIR_OPCODES.I64_MUL:
|
|
569
|
-
frame.push(BigInt(frame.pop()) * BigInt(frame.pop()));
|
|
570
|
-
this.pc++;
|
|
571
|
-
break;
|
|
572
|
-
|
|
573
|
-
// ═══════════════════════════════════════════════════════════════
|
|
574
|
-
// COMPARISON OPERATIONS
|
|
575
|
-
// ═══════════════════════════════════════════════════════════════
|
|
576
|
-
|
|
577
|
-
case JIR_OPCODES.I32_EQ:
|
|
578
|
-
frame.push(frame.pop() === frame.pop() ? 1 : 0);
|
|
579
|
-
this.pc++;
|
|
580
|
-
break;
|
|
581
|
-
|
|
582
|
-
case JIR_OPCODES.I32_NE:
|
|
583
|
-
frame.push(frame.pop() !== frame.pop() ? 1 : 0);
|
|
584
|
-
this.pc++;
|
|
585
|
-
break;
|
|
586
|
-
|
|
587
|
-
case JIR_OPCODES.I32_LT_S:
|
|
588
|
-
const lt2 = frame.pop();
|
|
589
|
-
const lt1 = frame.pop();
|
|
590
|
-
frame.push(lt1 < lt2 ? 1 : 0);
|
|
591
|
-
this.pc++;
|
|
592
|
-
break;
|
|
593
|
-
|
|
594
|
-
case JIR_OPCODES.I32_GT_S:
|
|
595
|
-
const gt2 = frame.pop();
|
|
596
|
-
const gt1 = frame.pop();
|
|
597
|
-
frame.push(gt1 > gt2 ? 1 : 0);
|
|
598
|
-
this.pc++;
|
|
599
|
-
break;
|
|
600
|
-
|
|
601
|
-
// ═══════════════════════════════════════════════════════════════
|
|
602
|
-
// BITWISE OPERATIONS
|
|
603
|
-
// ═══════════════════════════════════════════════════════════════
|
|
604
|
-
|
|
605
|
-
case JIR_OPCODES.I32_AND:
|
|
606
|
-
frame.push(frame.pop() & frame.pop());
|
|
607
|
-
this.pc++;
|
|
608
|
-
break;
|
|
609
|
-
|
|
610
|
-
case JIR_OPCODES.I32_OR:
|
|
611
|
-
frame.push(frame.pop() | frame.pop());
|
|
612
|
-
this.pc++;
|
|
613
|
-
break;
|
|
614
|
-
|
|
615
|
-
case JIR_OPCODES.I32_XOR:
|
|
616
|
-
frame.push(frame.pop() ^ frame.pop());
|
|
617
|
-
this.pc++;
|
|
618
|
-
break;
|
|
619
|
-
|
|
620
|
-
case JIR_OPCODES.I32_SHL:
|
|
621
|
-
const shl2 = frame.pop();
|
|
622
|
-
const shl1 = frame.pop();
|
|
623
|
-
frame.push(shl1 << shl2);
|
|
624
|
-
this.pc++;
|
|
625
|
-
break;
|
|
626
|
-
|
|
627
|
-
case JIR_OPCODES.I32_SHR_S:
|
|
628
|
-
const shr2 = frame.pop();
|
|
629
|
-
const shr1 = frame.pop();
|
|
630
|
-
frame.push(shr1 >> shr2);
|
|
631
|
-
this.pc++;
|
|
632
|
-
break;
|
|
633
|
-
|
|
634
|
-
case JIR_OPCODES.I32_SHR_U:
|
|
635
|
-
const shru2 = frame.pop();
|
|
636
|
-
const shru1 = frame.pop();
|
|
637
|
-
frame.push(shru1 >>> shru2);
|
|
638
|
-
this.pc++;
|
|
639
|
-
break;
|
|
640
|
-
|
|
641
|
-
// ═══════════════════════════════════════════════════════════════
|
|
642
|
-
// BLOCKCHAIN OPERATIONS
|
|
643
|
-
// ═══════════════════════════════════════════════════════════════
|
|
644
|
-
|
|
645
|
-
case JIR_OPCODES.SLOAD:
|
|
646
|
-
const slot = frame.pop();
|
|
647
|
-
const stored = await this._sload(slot);
|
|
648
|
-
frame.push(stored);
|
|
649
|
-
this.pc++;
|
|
650
|
-
break;
|
|
651
|
-
|
|
652
|
-
case JIR_OPCODES.SSTORE:
|
|
653
|
-
const value = frame.pop();
|
|
654
|
-
const key = frame.pop();
|
|
655
|
-
await this._sstore(key, value);
|
|
656
|
-
this.pc++;
|
|
657
|
-
break;
|
|
658
|
-
|
|
659
|
-
case JIR_OPCODES.BALANCE:
|
|
660
|
-
const balAddr = frame.pop();
|
|
661
|
-
const balance = await this._getBalance(balAddr);
|
|
662
|
-
frame.push(balance);
|
|
663
|
-
this.pc++;
|
|
664
|
-
break;
|
|
665
|
-
|
|
666
|
-
case JIR_OPCODES.TRANSFER:
|
|
667
|
-
const amount = frame.pop();
|
|
668
|
-
const toAddr = frame.pop();
|
|
669
|
-
await this._transfer(toAddr, amount);
|
|
670
|
-
this.pc++;
|
|
671
|
-
break;
|
|
672
|
-
|
|
673
|
-
case JIR_OPCODES.CONTRACT_CALL:
|
|
674
|
-
const callGas = frame.pop();
|
|
675
|
-
const callValue = frame.pop();
|
|
676
|
-
const callTarget = frame.pop();
|
|
677
|
-
const callData = this._popBytes(frame);
|
|
678
|
-
const callResult = await this._contractCall(callTarget, callValue, callData, callGas);
|
|
679
|
-
frame.push(callResult.success ? 1 : 0);
|
|
680
|
-
this._pushBytes(frame, callResult.returnData);
|
|
681
|
-
this.pc++;
|
|
682
|
-
break;
|
|
683
|
-
|
|
684
|
-
case JIR_OPCODES.CALLER:
|
|
685
|
-
frame.push(this._addressToNum(this.context.caller));
|
|
686
|
-
this.pc++;
|
|
687
|
-
break;
|
|
688
|
-
|
|
689
|
-
case JIR_OPCODES.ORIGIN:
|
|
690
|
-
frame.push(this._addressToNum(this.context.origin));
|
|
691
|
-
this.pc++;
|
|
692
|
-
break;
|
|
693
|
-
|
|
694
|
-
case JIR_OPCODES.CALLVALUE:
|
|
695
|
-
frame.push(this.context.value);
|
|
696
|
-
this.pc++;
|
|
697
|
-
break;
|
|
698
|
-
|
|
699
|
-
case JIR_OPCODES.TIMESTAMP:
|
|
700
|
-
frame.push(this.context.timestamp);
|
|
701
|
-
this.pc++;
|
|
702
|
-
break;
|
|
703
|
-
|
|
704
|
-
case JIR_OPCODES.BLOCKNUMBER:
|
|
705
|
-
frame.push(this.context.blockNumber);
|
|
706
|
-
this.pc++;
|
|
707
|
-
break;
|
|
708
|
-
|
|
709
|
-
case JIR_OPCODES.CHAINID:
|
|
710
|
-
frame.push(this.context.chainId);
|
|
711
|
-
this.pc++;
|
|
712
|
-
break;
|
|
713
|
-
|
|
714
|
-
// ═══════════════════════════════════════════════════════════════
|
|
715
|
-
// CRYPTO OPERATIONS
|
|
716
|
-
// ═══════════════════════════════════════════════════════════════
|
|
717
|
-
|
|
718
|
-
case JIR_OPCODES.SHA256:
|
|
719
|
-
const sha256Data = this._popBytes(frame);
|
|
720
|
-
const sha256Hash = crypto.createHash('sha256').update(sha256Data).digest();
|
|
721
|
-
this._pushBytes(frame, sha256Hash);
|
|
722
|
-
this.pc++;
|
|
723
|
-
break;
|
|
724
|
-
|
|
725
|
-
case JIR_OPCODES.KECCAK256:
|
|
726
|
-
const keccakData = this._popBytes(frame);
|
|
727
|
-
// Using sha3-256 as a placeholder (proper keccak would need external lib)
|
|
728
|
-
const keccakHash = crypto.createHash('sha3-256').update(keccakData).digest();
|
|
729
|
-
this._pushBytes(frame, keccakHash);
|
|
730
|
-
this.pc++;
|
|
731
|
-
break;
|
|
732
|
-
|
|
733
|
-
// ═══════════════════════════════════════════════════════════════
|
|
734
|
-
// LOGGING
|
|
735
|
-
// ═══════════════════════════════════════════════════════════════
|
|
736
|
-
|
|
737
|
-
case JIR_OPCODES.LOG0:
|
|
738
|
-
case JIR_OPCODES.LOG1:
|
|
739
|
-
case JIR_OPCODES.LOG2:
|
|
740
|
-
case JIR_OPCODES.LOG3:
|
|
741
|
-
case JIR_OPCODES.LOG4:
|
|
742
|
-
const numTopics = opcode - JIR_OPCODES.LOG0;
|
|
743
|
-
const logData = this._popBytes(frame);
|
|
744
|
-
const topics = [];
|
|
745
|
-
for (let i = 0; i < numTopics; i++) {
|
|
746
|
-
topics.push(frame.pop());
|
|
747
|
-
}
|
|
748
|
-
this.logs.push({
|
|
749
|
-
address: this.context.address,
|
|
750
|
-
topics,
|
|
751
|
-
data: logData
|
|
752
|
-
});
|
|
753
|
-
this.pc++;
|
|
754
|
-
break;
|
|
755
|
-
|
|
756
|
-
// ═══════════════════════════════════════════════════════════════
|
|
757
|
-
// CROSS-VM OPERATIONS (JAELIS SPECIFIC!)
|
|
758
|
-
// ═══════════════════════════════════════════════════════════════
|
|
759
|
-
|
|
760
|
-
case JIR_OPCODES.CROSS_VM_CALL:
|
|
761
|
-
const targetVM = frame.pop(); // Target VM type
|
|
762
|
-
const targetAddr = frame.pop(); // Target address
|
|
763
|
-
const crossCallData = this._popBytes(frame);
|
|
764
|
-
const crossResult = await this._crossVMCall(targetVM, targetAddr, crossCallData);
|
|
765
|
-
frame.push(crossResult.success ? 1 : 0);
|
|
766
|
-
this._pushBytes(frame, crossResult.returnData);
|
|
767
|
-
this.pc++;
|
|
768
|
-
break;
|
|
769
|
-
|
|
770
|
-
case JIR_OPCODES.CROSS_VM_STATE:
|
|
771
|
-
const stateVM = frame.pop();
|
|
772
|
-
const stateAddr = frame.pop();
|
|
773
|
-
const stateSlot = frame.pop();
|
|
774
|
-
const stateValue = await this._crossVMState(stateVM, stateAddr, stateSlot);
|
|
775
|
-
frame.push(stateValue);
|
|
776
|
-
this.pc++;
|
|
777
|
-
break;
|
|
778
|
-
|
|
779
|
-
// ═══════════════════════════════════════════════════════════════
|
|
780
|
-
// METERING
|
|
781
|
-
// ═══════════════════════════════════════════════════════════════
|
|
782
|
-
|
|
783
|
-
case JIR_OPCODES.GAS:
|
|
784
|
-
frame.push(this.gasLimit - this.gasUsed);
|
|
785
|
-
this.pc++;
|
|
786
|
-
break;
|
|
787
|
-
|
|
788
|
-
case JIR_OPCODES.LODE_SIGNAL:
|
|
789
|
-
frame.push(0); // JAELIS is zero-fee!
|
|
790
|
-
this.pc++;
|
|
791
|
-
break;
|
|
792
|
-
|
|
793
|
-
// ═══════════════════════════════════════════════════════════════
|
|
794
|
-
// DEBUG
|
|
795
|
-
// ═══════════════════════════════════════════════════════════════
|
|
796
|
-
|
|
797
|
-
case JIR_OPCODES.DEBUG_PRINT:
|
|
798
|
-
if (this.config.debug) {
|
|
799
|
-
const printVal = frame.pop();
|
|
800
|
-
console.log(`[DEBUG] ${printVal}`);
|
|
801
|
-
}
|
|
802
|
-
this.pc++;
|
|
803
|
-
break;
|
|
804
|
-
|
|
805
|
-
// ═══════════════════════════════════════════════════════════════
|
|
806
|
-
// HALT
|
|
807
|
-
// ═══════════════════════════════════════════════════════════════
|
|
808
|
-
|
|
809
|
-
case JIR_OPCODES.REVERT:
|
|
810
|
-
this.halted = true;
|
|
811
|
-
this.running = false;
|
|
812
|
-
break;
|
|
813
|
-
|
|
814
|
-
case JIR_OPCODES.HALT:
|
|
815
|
-
this.running = false;
|
|
816
|
-
break;
|
|
817
|
-
|
|
818
|
-
default:
|
|
819
|
-
if (this.config.debug) {
|
|
820
|
-
console.log(`[Engine] Unknown opcode: 0x${opcode.toString(16)}`);
|
|
821
|
-
}
|
|
822
|
-
this.pc++;
|
|
823
|
-
break;
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
// ═══════════════════════════════════════════════════════════════
|
|
828
|
-
// AOT MODE (Ahead-of-Time Compilation)
|
|
829
|
-
// ═══════════════════════════════════════════════════════════════
|
|
830
|
-
|
|
831
|
-
async _executeAOT(jir, func, args) {
|
|
832
|
-
const cacheKey = `${jir.metadata.sourceHash}:${func.name}`;
|
|
833
|
-
|
|
834
|
-
// Check cache
|
|
835
|
-
if (!this.aotCache.has(cacheKey)) {
|
|
836
|
-
// Compile to native JavaScript
|
|
837
|
-
const compiled = this._compileToJS(jir, func);
|
|
838
|
-
this.aotCache.set(cacheKey, compiled);
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
const compiledFunc = this.aotCache.get(cacheKey);
|
|
842
|
-
|
|
843
|
-
// Execute compiled function
|
|
844
|
-
const result = await compiledFunc.call(this, args, this.context);
|
|
845
|
-
|
|
846
|
-
return {
|
|
847
|
-
success: true,
|
|
848
|
-
returnData: this._serializeReturn(result)
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
_compileToJS(jir, func) {
|
|
853
|
-
// Generate JavaScript code from JIR
|
|
854
|
-
// This is a simplified version - real AOT would be much more sophisticated
|
|
855
|
-
|
|
856
|
-
const jsCode = `
|
|
857
|
-
return async function(args, context) {
|
|
858
|
-
// Compiled function: ${func.name}
|
|
859
|
-
const locals = [...args];
|
|
860
|
-
let result = 0;
|
|
861
|
-
|
|
862
|
-
// Function body would be generated here
|
|
863
|
-
// based on the JIR bytecode
|
|
864
|
-
|
|
865
|
-
return result;
|
|
866
|
-
}
|
|
867
|
-
`;
|
|
868
|
-
|
|
869
|
-
return new Function(jsCode)();
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
// ═══════════════════════════════════════════════════════════════
|
|
873
|
-
// JIT MODE (Just-in-Time Compilation)
|
|
874
|
-
// ═══════════════════════════════════════════════════════════════
|
|
875
|
-
|
|
876
|
-
async _executeJIT(jir, func, args) {
|
|
877
|
-
const cacheKey = `${jir.metadata.sourceHash}:${func.name}`;
|
|
878
|
-
|
|
879
|
-
// Track execution counts
|
|
880
|
-
const stats = this.jitStats.get(cacheKey) || { count: 0, compiled: false };
|
|
881
|
-
stats.count++;
|
|
882
|
-
this.jitStats.set(cacheKey, stats);
|
|
883
|
-
|
|
884
|
-
// If hot, compile
|
|
885
|
-
if (stats.count >= this.jitThreshold && !stats.compiled) {
|
|
886
|
-
console.log(`[JIT] Compiling hot function: ${func.name}`);
|
|
887
|
-
const compiled = this._compileToJS(jir, func);
|
|
888
|
-
this.aotCache.set(cacheKey, compiled);
|
|
889
|
-
stats.compiled = true;
|
|
890
|
-
}
|
|
891
|
-
|
|
892
|
-
// Execute (compiled if available, otherwise interpreted)
|
|
893
|
-
if (stats.compiled) {
|
|
894
|
-
return this._executeAOT(jir, func, args);
|
|
895
|
-
} else {
|
|
896
|
-
return this._executeInterpreter(jir, func, args);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
|
|
900
|
-
// ═══════════════════════════════════════════════════════════════
|
|
901
|
-
// HELPER METHODS
|
|
902
|
-
// ═══════════════════════════════════════════════════════════════
|
|
903
|
-
|
|
904
|
-
_reset() {
|
|
905
|
-
this.memory = null;
|
|
906
|
-
this.memorySize = 0;
|
|
907
|
-
this.heap.clear();
|
|
908
|
-
this.heapNextId = 1;
|
|
909
|
-
this.globals.clear();
|
|
910
|
-
this.callStack = [];
|
|
911
|
-
this.pc = 0;
|
|
912
|
-
this.running = false;
|
|
913
|
-
this.halted = false;
|
|
914
|
-
this.instructionsExecuted = 0;
|
|
915
|
-
this.gasUsed = 0;
|
|
916
|
-
this.stateChanges = [];
|
|
917
|
-
this.logs = [];
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
_initMemory(memConfig) {
|
|
921
|
-
const initialPages = memConfig?.initial || 1;
|
|
922
|
-
this.memorySize = initialPages * 65536; // 64KB per page
|
|
923
|
-
this.memory = Buffer.alloc(this.memorySize);
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
_loadGlobals(globals) {
|
|
927
|
-
if (!globals) return;
|
|
928
|
-
globals.forEach((g, i) => {
|
|
929
|
-
this.globals.set(i, g.init || 0);
|
|
930
|
-
});
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
_loadData(data) {
|
|
934
|
-
if (!data) return;
|
|
935
|
-
for (const segment of data) {
|
|
936
|
-
if (segment.data && segment.offset !== undefined) {
|
|
937
|
-
segment.data.copy(this.memory, segment.offset);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
_findFunctionOffset(jir, func) {
|
|
943
|
-
// Find the bytecode offset for the function
|
|
944
|
-
// This is a simplified version
|
|
945
|
-
return 4; // Skip magic number
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
_parseArguments(args, params) {
|
|
949
|
-
// Parse serialized arguments based on function parameter types
|
|
950
|
-
if (!args || args.length === 0) return [];
|
|
951
|
-
|
|
952
|
-
// Simple parsing - would be more sophisticated with proper type handling
|
|
953
|
-
try {
|
|
954
|
-
if (Buffer.isBuffer(args)) {
|
|
955
|
-
// Try to parse as CBOR or MessagePack
|
|
956
|
-
return JSON.parse(args.toString());
|
|
957
|
-
}
|
|
958
|
-
return Array.isArray(args) ? args : [args];
|
|
959
|
-
} catch (e) {
|
|
960
|
-
return [];
|
|
961
|
-
}
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
_serializeReturn(value) {
|
|
965
|
-
if (value === null || value === undefined) {
|
|
966
|
-
return Buffer.alloc(0);
|
|
967
|
-
}
|
|
968
|
-
|
|
969
|
-
if (Buffer.isBuffer(value)) {
|
|
970
|
-
return value;
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
if (typeof value === 'bigint') {
|
|
974
|
-
const buf = Buffer.alloc(32);
|
|
975
|
-
let v = value;
|
|
976
|
-
for (let i = 31; i >= 0 && v > 0n; i--) {
|
|
977
|
-
buf[i] = Number(v & 0xffn);
|
|
978
|
-
v >>= 8n;
|
|
979
|
-
}
|
|
980
|
-
return buf;
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
if (typeof value === 'number') {
|
|
984
|
-
const buf = Buffer.alloc(8);
|
|
985
|
-
buf.writeBigInt64LE(BigInt(value));
|
|
986
|
-
return buf;
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
return Buffer.from(JSON.stringify(value));
|
|
990
|
-
}
|
|
991
|
-
|
|
992
|
-
_findElseOrEnd(bytecode, pc) {
|
|
993
|
-
let depth = 1;
|
|
994
|
-
let i = pc + 1;
|
|
995
|
-
while (depth > 0 && i < bytecode.length) {
|
|
996
|
-
if (bytecode[i] === JIR_OPCODES.IF || bytecode[i] === JIR_OPCODES.BLOCK || bytecode[i] === JIR_OPCODES.LOOP) {
|
|
997
|
-
depth++;
|
|
998
|
-
} else if (bytecode[i] === JIR_OPCODES.END) {
|
|
999
|
-
depth--;
|
|
1000
|
-
} else if (depth === 1 && bytecode[i] === JIR_OPCODES.ELSE) {
|
|
1001
|
-
return i + 1;
|
|
1002
|
-
}
|
|
1003
|
-
i++;
|
|
1004
|
-
}
|
|
1005
|
-
return i;
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
_findEnd(bytecode, pc) {
|
|
1009
|
-
let depth = 1;
|
|
1010
|
-
let i = pc + 1;
|
|
1011
|
-
while (depth > 0 && i < bytecode.length) {
|
|
1012
|
-
if (bytecode[i] === JIR_OPCODES.IF || bytecode[i] === JIR_OPCODES.BLOCK || bytecode[i] === JIR_OPCODES.LOOP) {
|
|
1013
|
-
depth++;
|
|
1014
|
-
} else if (bytecode[i] === JIR_OPCODES.END) {
|
|
1015
|
-
depth--;
|
|
1016
|
-
}
|
|
1017
|
-
i++;
|
|
1018
|
-
}
|
|
1019
|
-
return i;
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
_branch(depth, frame) {
|
|
1023
|
-
// Branch to outer block
|
|
1024
|
-
for (let i = 0; i < depth && frame.blockStack.length > 0; i++) {
|
|
1025
|
-
frame.blockStack.pop();
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
if (frame.blockStack.length > 0) {
|
|
1029
|
-
const block = frame.blockStack[frame.blockStack.length - 1];
|
|
1030
|
-
if (block.type === 'loop') {
|
|
1031
|
-
this.pc = block.pc + 1; // Jump to loop start
|
|
1032
|
-
} else {
|
|
1033
|
-
// Jump to end of block
|
|
1034
|
-
this.pc = this._findEnd(this.memory, block.pc);
|
|
1035
|
-
}
|
|
1036
|
-
} else {
|
|
1037
|
-
this.running = false;
|
|
1038
|
-
}
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
async _call(funcIdx, jir) {
|
|
1042
|
-
// Call another function
|
|
1043
|
-
if (funcIdx < jir.functions.length) {
|
|
1044
|
-
const func = jir.functions[funcIdx];
|
|
1045
|
-
const frame = this.callStack[this.callStack.length - 1];
|
|
1046
|
-
|
|
1047
|
-
// Pop arguments from caller's stack
|
|
1048
|
-
const args = [];
|
|
1049
|
-
for (let i = 0; i < (func.params?.length || 0); i++) {
|
|
1050
|
-
args.unshift(frame.pop());
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
// Create new frame
|
|
1054
|
-
const newFrame = new StackFrame(funcIdx, this.pc + 1, args);
|
|
1055
|
-
this.callStack.push(newFrame);
|
|
1056
|
-
|
|
1057
|
-
// Jump to function
|
|
1058
|
-
this.pc = this._findFunctionOffset(jir, func);
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
async _callIndirect(tableIdx, typeIdx, funcRef, jir) {
|
|
1063
|
-
// Indirect call through table
|
|
1064
|
-
if (this.tables[tableIdx] && this.tables[tableIdx][funcRef]) {
|
|
1065
|
-
await this._call(this.tables[tableIdx][funcRef], jir);
|
|
1066
|
-
} else {
|
|
1067
|
-
throw new Error('Invalid indirect call');
|
|
1068
|
-
}
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
_popBytes(frame) {
|
|
1072
|
-
const size = Number(frame.pop());
|
|
1073
|
-
const offset = Number(frame.pop());
|
|
1074
|
-
return this.memory.slice(offset, offset + size);
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
_pushBytes(frame, data) {
|
|
1078
|
-
// Write to memory and push offset/size
|
|
1079
|
-
const offset = this._allocateMemory(data.length);
|
|
1080
|
-
data.copy(this.memory, offset);
|
|
1081
|
-
frame.push(offset);
|
|
1082
|
-
frame.push(data.length);
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
_allocateMemory(size) {
|
|
1086
|
-
// Simple bump allocator
|
|
1087
|
-
const offset = this.heapNextId;
|
|
1088
|
-
this.heapNextId += size;
|
|
1089
|
-
if (this.heapNextId > this.memorySize) {
|
|
1090
|
-
// Grow memory
|
|
1091
|
-
const newSize = Math.min(this.memorySize * 2, this.config.maxMemory);
|
|
1092
|
-
const newMemory = Buffer.alloc(newSize);
|
|
1093
|
-
this.memory.copy(newMemory);
|
|
1094
|
-
this.memory = newMemory;
|
|
1095
|
-
this.memorySize = newSize;
|
|
1096
|
-
}
|
|
1097
|
-
return offset;
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
_addressToNum(addr) {
|
|
1101
|
-
// Convert address string to BigInt
|
|
1102
|
-
if (typeof addr === 'string') {
|
|
1103
|
-
return BigInt(addr);
|
|
1104
|
-
}
|
|
1105
|
-
return BigInt(addr);
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
// ═══════════════════════════════════════════════════════════════
|
|
1109
|
-
// BLOCKCHAIN HOST FUNCTIONS
|
|
1110
|
-
// ═══════════════════════════════════════════════════════════════
|
|
1111
|
-
|
|
1112
|
-
_registerHostFunctions() {
|
|
1113
|
-
// Register blockchain operations as host functions
|
|
1114
|
-
this.hostFunctions.set('sload', this._sload.bind(this));
|
|
1115
|
-
this.hostFunctions.set('sstore', this._sstore.bind(this));
|
|
1116
|
-
this.hostFunctions.set('balance', this._getBalance.bind(this));
|
|
1117
|
-
this.hostFunctions.set('transfer', this._transfer.bind(this));
|
|
1118
|
-
this.hostFunctions.set('call', this._contractCall.bind(this));
|
|
1119
|
-
this.hostFunctions.set('crossVMCall', this._crossVMCall.bind(this));
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
async _sload(slot) {
|
|
1123
|
-
// Load from contract storage
|
|
1124
|
-
// This would interface with StateManager
|
|
1125
|
-
this.emit('sload', { address: this.context.address, slot });
|
|
1126
|
-
return 0n; // Placeholder
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
async _sstore(key, value) {
|
|
1130
|
-
// Store to contract storage
|
|
1131
|
-
this.stateChanges.push({
|
|
1132
|
-
type: 'storage',
|
|
1133
|
-
address: this.context.address,
|
|
1134
|
-
key,
|
|
1135
|
-
value
|
|
1136
|
-
});
|
|
1137
|
-
this.emit('sstore', { address: this.context.address, key, value });
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
async _getBalance(address) {
|
|
1141
|
-
// Get balance of address
|
|
1142
|
-
this.emit('balance', { address });
|
|
1143
|
-
return 0n; // Placeholder
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
async _transfer(to, amount) {
|
|
1147
|
-
// Transfer native token
|
|
1148
|
-
this.stateChanges.push({
|
|
1149
|
-
type: 'transfer',
|
|
1150
|
-
from: this.context.caller,
|
|
1151
|
-
to,
|
|
1152
|
-
amount
|
|
1153
|
-
});
|
|
1154
|
-
this.emit('transfer', { from: this.context.caller, to, amount });
|
|
1155
|
-
}
|
|
1156
|
-
|
|
1157
|
-
async _contractCall(target, value, data, gas) {
|
|
1158
|
-
// Call another contract
|
|
1159
|
-
this.emit('call', { target, value, data, gas });
|
|
1160
|
-
return {
|
|
1161
|
-
success: true,
|
|
1162
|
-
returnData: Buffer.alloc(0)
|
|
1163
|
-
};
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
async _crossVMCall(targetVM, targetAddr, data) {
|
|
1167
|
-
// Cross-VM call (JAELIS specific!)
|
|
1168
|
-
console.log(`[Engine] Cross-VM call to VM=${targetVM} addr=${targetAddr}`);
|
|
1169
|
-
this.emit('crossVMCall', { targetVM, targetAddr, data });
|
|
1170
|
-
return {
|
|
1171
|
-
success: true,
|
|
1172
|
-
returnData: Buffer.alloc(0)
|
|
1173
|
-
};
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
async _crossVMState(vm, addr, slot) {
|
|
1177
|
-
// Read state from another VM's contract
|
|
1178
|
-
this.emit('crossVMState', { vm, addr, slot });
|
|
1179
|
-
return 0n; // Placeholder
|
|
1180
|
-
}
|
|
1181
|
-
}
|
|
1182
|
-
|
|
1183
|
-
module.exports = ExecutionEngine;
|