jaelis-node 1.10.0 → 2.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.
- package/README.md +146 -445
- package/bin/jaelis-node.js +79 -504
- package/lib/index.js +31 -2840
- package/lib/node.js +271 -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,1127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JAELIS DYNAMIC CONTRACTS
|
|
3
|
-
*
|
|
4
|
-
* Contracts that can UPDATE THEMSELVES when the underlying
|
|
5
|
-
* VM specs change. No more "deploy new version" BS.
|
|
6
|
-
*
|
|
7
|
-
* How it works:
|
|
8
|
-
* 1. Contracts are stored as UNIFIED AST, not frozen bytecode
|
|
9
|
-
* 2. When VM specs update, contracts auto-recompile
|
|
10
|
-
* 3. State is preserved, only logic updates
|
|
11
|
-
* 4. Cross-contract calls automatically adapt
|
|
12
|
-
*
|
|
13
|
-
* Example:
|
|
14
|
-
* - Solana adds a new opcode for faster hashing
|
|
15
|
-
* - Our unified compiler absorbs the new opcode
|
|
16
|
-
* - ALL contracts that use hashing get faster automatically
|
|
17
|
-
* - No migration, no upgrade, no downtime
|
|
18
|
-
*
|
|
19
|
-
* @version 0.2.0
|
|
20
|
-
* @author Mario Papaleo - JAELIS Foundation
|
|
21
|
-
* @patent PATENT PENDING - Self-Updating Smart Contracts
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
const crypto = require('crypto');
|
|
25
|
-
const EventEmitter = require('events');
|
|
26
|
-
const { UnifiedCompiler } = require('./unified-compiler');
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Contract State Store
|
|
30
|
-
*
|
|
31
|
-
* Separates state from logic - key for dynamic updates!
|
|
32
|
-
* Now backed by Core StateManager for LevelDB persistence.
|
|
33
|
-
*
|
|
34
|
-
* Architecture (Patent Claim 7d - Unified State Manager):
|
|
35
|
-
* ContractStateStore → Core StateManager → LevelDB
|
|
36
|
-
*/
|
|
37
|
-
class ContractStateStore {
|
|
38
|
-
constructor(contractAddress = null) {
|
|
39
|
-
// Contract address for namespacing
|
|
40
|
-
this._contractAddress = contractAddress;
|
|
41
|
-
|
|
42
|
-
// Core StateManager reference (LevelDB backend)
|
|
43
|
-
this._coreState = null;
|
|
44
|
-
this._connected = false;
|
|
45
|
-
|
|
46
|
-
// Local cache for fast reads (synced with LevelDB)
|
|
47
|
-
this._slots = new Map();
|
|
48
|
-
|
|
49
|
-
// State version tracking
|
|
50
|
-
this.versions = new Map();
|
|
51
|
-
|
|
52
|
-
// State snapshots for rollback
|
|
53
|
-
this.snapshots = [];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Connect to Core StateManager for LevelDB persistence
|
|
58
|
-
*/
|
|
59
|
-
connectCoreState(coreStateManager, contractAddress = null) {
|
|
60
|
-
this._coreState = coreStateManager;
|
|
61
|
-
this._connected = true;
|
|
62
|
-
if (contractAddress) {
|
|
63
|
-
this._contractAddress = contractAddress;
|
|
64
|
-
}
|
|
65
|
-
console.log(`[ContractStateStore] Connected to Core StateManager (LevelDB)`);
|
|
66
|
-
return this;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Check if connected to Core StateManager
|
|
71
|
-
*/
|
|
72
|
-
isConnected() {
|
|
73
|
-
return this._connected && this._coreState !== null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Legacy slots getter for compatibility
|
|
78
|
-
*/
|
|
79
|
-
get slots() {
|
|
80
|
-
return this._slots;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
read(slot) {
|
|
84
|
-
const key = typeof slot === 'string' ? slot : slot.toString('hex');
|
|
85
|
-
|
|
86
|
-
// Check local cache
|
|
87
|
-
if (this._slots.has(key)) {
|
|
88
|
-
return this._slots.get(key);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return Buffer.alloc(32);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Async read with LevelDB fallback
|
|
96
|
-
*/
|
|
97
|
-
async readAsync(slot) {
|
|
98
|
-
const key = typeof slot === 'string' ? slot : slot.toString('hex');
|
|
99
|
-
|
|
100
|
-
// Check local cache
|
|
101
|
-
if (this._slots.has(key)) {
|
|
102
|
-
return this._slots.get(key);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Try Core StateManager (LevelDB)
|
|
106
|
-
if (this._coreState && this._contractAddress) {
|
|
107
|
-
try {
|
|
108
|
-
const value = await this._coreState.getStorage(this._contractAddress, '0x' + key);
|
|
109
|
-
if (value && value !== '0x' + '0'.repeat(64)) {
|
|
110
|
-
const buffer = Buffer.from(value.replace('0x', ''), 'hex');
|
|
111
|
-
this._slots.set(key, buffer);
|
|
112
|
-
return buffer;
|
|
113
|
-
}
|
|
114
|
-
} catch (e) {
|
|
115
|
-
// Slot empty
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return Buffer.alloc(32);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
write(slot, value) {
|
|
123
|
-
const key = typeof slot === 'string' ? slot : slot.toString('hex');
|
|
124
|
-
const oldValue = this._slots.get(key);
|
|
125
|
-
|
|
126
|
-
this._slots.set(key, value);
|
|
127
|
-
|
|
128
|
-
// Track version
|
|
129
|
-
const version = (this.versions.get(key) || 0) + 1;
|
|
130
|
-
this.versions.set(key, version);
|
|
131
|
-
|
|
132
|
-
// Persist to Core StateManager (LevelDB) - async fire and forget
|
|
133
|
-
if (this._coreState && this._contractAddress) {
|
|
134
|
-
const hexValue = Buffer.isBuffer(value) ? '0x' + value.toString('hex') : value;
|
|
135
|
-
this._coreState.setStorage(this._contractAddress, '0x' + key, hexValue)
|
|
136
|
-
.catch(err => console.error('[ContractStateStore] LevelDB write error:', err));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return { slot, oldValue, newValue: value, version };
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Async write with await for LevelDB
|
|
144
|
-
*/
|
|
145
|
-
async writeAsync(slot, value) {
|
|
146
|
-
const key = typeof slot === 'string' ? slot : slot.toString('hex');
|
|
147
|
-
const oldValue = this._slots.get(key);
|
|
148
|
-
|
|
149
|
-
this._slots.set(key, value);
|
|
150
|
-
|
|
151
|
-
// Track version
|
|
152
|
-
const version = (this.versions.get(key) || 0) + 1;
|
|
153
|
-
this.versions.set(key, version);
|
|
154
|
-
|
|
155
|
-
// Persist to Core StateManager (LevelDB)
|
|
156
|
-
if (this._coreState && this._contractAddress) {
|
|
157
|
-
const hexValue = Buffer.isBuffer(value) ? '0x' + value.toString('hex') : value;
|
|
158
|
-
await this._coreState.setStorage(this._contractAddress, '0x' + key, hexValue);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return { slot, oldValue, newValue: value, version };
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
snapshot() {
|
|
165
|
-
const id = this.snapshots.length;
|
|
166
|
-
this.snapshots.push(new Map(this._slots));
|
|
167
|
-
|
|
168
|
-
// Also snapshot Core StateManager if connected
|
|
169
|
-
if (this._coreState && this._coreState.snapshot) {
|
|
170
|
-
this._coreSnapshotId = this._coreState.snapshot();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return id;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
rollback(snapshotId) {
|
|
177
|
-
if (snapshotId < this.snapshots.length) {
|
|
178
|
-
this._slots = new Map(this.snapshots[snapshotId]);
|
|
179
|
-
|
|
180
|
-
// Also rollback Core StateManager if connected
|
|
181
|
-
if (this._coreState && this._coreState.revertToSnapshot && this._coreSnapshotId !== undefined) {
|
|
182
|
-
this._coreState.revertToSnapshot(this._coreSnapshotId);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Get stats
|
|
189
|
-
*/
|
|
190
|
-
getStats() {
|
|
191
|
-
return {
|
|
192
|
-
connected: this._connected,
|
|
193
|
-
contractAddress: this._contractAddress,
|
|
194
|
-
cachedSlots: this._slots.size,
|
|
195
|
-
versions: this.versions.size,
|
|
196
|
-
snapshots: this.snapshots.length
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Dynamic Contract
|
|
203
|
-
*
|
|
204
|
-
* A contract that stores both its AST and bytecode,
|
|
205
|
-
* allowing it to recompile when VM specs change.
|
|
206
|
-
*/
|
|
207
|
-
class DynamicContract extends EventEmitter {
|
|
208
|
-
constructor(address, source, language) {
|
|
209
|
-
super();
|
|
210
|
-
|
|
211
|
-
this.address = address;
|
|
212
|
-
this.source = source; // Original source code
|
|
213
|
-
this.language = language; // Original language
|
|
214
|
-
this.ast = null; // Unified AST
|
|
215
|
-
this.bytecode = null; // Current bytecode
|
|
216
|
-
this.version = 0; // Contract version
|
|
217
|
-
this.state = new ContractStateStore();
|
|
218
|
-
|
|
219
|
-
// Interface definition (for cross-contract calls)
|
|
220
|
-
this.interface = {
|
|
221
|
-
functions: new Map(),
|
|
222
|
-
events: new Map(),
|
|
223
|
-
errors: new Map()
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
// Upgrade history
|
|
227
|
-
this.history = [];
|
|
228
|
-
|
|
229
|
-
// Dependencies on other contracts
|
|
230
|
-
this.dependencies = new Set();
|
|
231
|
-
|
|
232
|
-
// Contracts that depend on us
|
|
233
|
-
this.dependents = new Set();
|
|
234
|
-
|
|
235
|
-
// Last compilation timestamp
|
|
236
|
-
this.lastCompiled = null;
|
|
237
|
-
|
|
238
|
-
// Compiler version used
|
|
239
|
-
this.compilerVersion = null;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Compile/recompile the contract
|
|
244
|
-
*/
|
|
245
|
-
async compile(compiler) {
|
|
246
|
-
console.log(`[DynamicContract] Compiling ${this.address.substring(0, 16)}...`);
|
|
247
|
-
|
|
248
|
-
const startTime = Date.now();
|
|
249
|
-
|
|
250
|
-
// Store old bytecode for rollback
|
|
251
|
-
const oldBytecode = this.bytecode;
|
|
252
|
-
const oldVersion = this.version;
|
|
253
|
-
|
|
254
|
-
try {
|
|
255
|
-
// Compile to unified AST
|
|
256
|
-
const result = await compiler.compile([{
|
|
257
|
-
name: this.address,
|
|
258
|
-
code: this.source,
|
|
259
|
-
language: this.language
|
|
260
|
-
}]);
|
|
261
|
-
|
|
262
|
-
this.ast = result.asts[0];
|
|
263
|
-
this.bytecode = result.bytecode;
|
|
264
|
-
this.version++;
|
|
265
|
-
this.lastCompiled = Date.now();
|
|
266
|
-
this.compilerVersion = '0.2.0';
|
|
267
|
-
|
|
268
|
-
// Update interface
|
|
269
|
-
this.updateInterface();
|
|
270
|
-
|
|
271
|
-
// Record in history
|
|
272
|
-
this.history.push({
|
|
273
|
-
version: this.version,
|
|
274
|
-
timestamp: this.lastCompiled,
|
|
275
|
-
bytecodeHash: crypto.createHash('sha256').update(this.bytecode).digest('hex'),
|
|
276
|
-
reason: 'compilation'
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
console.log(`[DynamicContract] Compiled v${this.version} in ${Date.now() - startTime}ms`);
|
|
280
|
-
|
|
281
|
-
this.emit('compiled', { version: this.version });
|
|
282
|
-
|
|
283
|
-
return true;
|
|
284
|
-
|
|
285
|
-
} catch (error) {
|
|
286
|
-
// Rollback
|
|
287
|
-
this.bytecode = oldBytecode;
|
|
288
|
-
this.version = oldVersion;
|
|
289
|
-
console.error(`[DynamicContract] Compilation failed: ${error.message}`);
|
|
290
|
-
throw error;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Update when VM specs change
|
|
296
|
-
*/
|
|
297
|
-
async upgrade(compiler, reason = 'vm-upgrade') {
|
|
298
|
-
console.log(`[DynamicContract] Upgrading due to: ${reason}`);
|
|
299
|
-
|
|
300
|
-
// Snapshot state before upgrade
|
|
301
|
-
const stateSnapshot = this.state.snapshot();
|
|
302
|
-
|
|
303
|
-
try {
|
|
304
|
-
// Recompile with new compiler
|
|
305
|
-
await this.compile(compiler);
|
|
306
|
-
|
|
307
|
-
// Record upgrade
|
|
308
|
-
this.history[this.history.length - 1].reason = reason;
|
|
309
|
-
|
|
310
|
-
this.emit('upgraded', { version: this.version, reason });
|
|
311
|
-
|
|
312
|
-
// Notify dependents
|
|
313
|
-
for (const dependent of this.dependents) {
|
|
314
|
-
this.emit('dependentNeedsUpgrade', { dependent, reason });
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
return true;
|
|
318
|
-
|
|
319
|
-
} catch (error) {
|
|
320
|
-
// Rollback state
|
|
321
|
-
this.state.rollback(stateSnapshot);
|
|
322
|
-
throw error;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Update interface from AST
|
|
328
|
-
*/
|
|
329
|
-
updateInterface() {
|
|
330
|
-
this.interface.functions.clear();
|
|
331
|
-
this.interface.events.clear();
|
|
332
|
-
|
|
333
|
-
if (!this.ast) return;
|
|
334
|
-
|
|
335
|
-
for (const contract of this.ast.contracts || []) {
|
|
336
|
-
for (const func of contract.functions || []) {
|
|
337
|
-
this.interface.functions.set(func.name, {
|
|
338
|
-
name: func.name,
|
|
339
|
-
selector: this.computeSelector(func.name, func.params),
|
|
340
|
-
params: func.params,
|
|
341
|
-
returns: func.returns,
|
|
342
|
-
visibility: func.visibility,
|
|
343
|
-
mutability: func.mutability
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
computeSelector(name, params) {
|
|
350
|
-
const signature = `${name}(${(params || []).map(p => p.type || 'uint256').join(',')})`;
|
|
351
|
-
return crypto.createHash('sha256').update(signature).digest().slice(0, 4);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/**
|
|
355
|
-
* Get contract ABI (compatible with all VMs!)
|
|
356
|
-
*/
|
|
357
|
-
getABI() {
|
|
358
|
-
const abi = [];
|
|
359
|
-
|
|
360
|
-
for (const [name, func] of this.interface.functions) {
|
|
361
|
-
abi.push({
|
|
362
|
-
type: 'function',
|
|
363
|
-
name: func.name,
|
|
364
|
-
inputs: (func.params || []).map(p => ({
|
|
365
|
-
name: p.name,
|
|
366
|
-
type: this.toABIType(p.type)
|
|
367
|
-
})),
|
|
368
|
-
outputs: (func.returns || []).map(r => ({
|
|
369
|
-
type: this.toABIType(r)
|
|
370
|
-
})),
|
|
371
|
-
stateMutability: func.mutability || 'nonpayable'
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
return abi;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
toABIType(unifiedType) {
|
|
379
|
-
const typeMap = {
|
|
380
|
-
'U256': 'uint256',
|
|
381
|
-
'U128': 'uint128',
|
|
382
|
-
'U64': 'uint64',
|
|
383
|
-
'U32': 'uint32',
|
|
384
|
-
'U8': 'uint8',
|
|
385
|
-
'I256': 'int256',
|
|
386
|
-
'BOOL': 'bool',
|
|
387
|
-
'ADDRESS': 'address',
|
|
388
|
-
'BYTES32': 'bytes32',
|
|
389
|
-
'BYTES': 'bytes',
|
|
390
|
-
'STRING': 'string'
|
|
391
|
-
};
|
|
392
|
-
return typeMap[unifiedType] || 'uint256';
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* Dynamic Contract Manager
|
|
398
|
-
*
|
|
399
|
-
* Manages all dynamic contracts, handles upgrades,
|
|
400
|
-
* and coordinates cross-contract updates.
|
|
401
|
-
*/
|
|
402
|
-
class DynamicContractManager extends EventEmitter {
|
|
403
|
-
constructor() {
|
|
404
|
-
super();
|
|
405
|
-
|
|
406
|
-
this.contracts = new Map();
|
|
407
|
-
this.compiler = new UnifiedCompiler();
|
|
408
|
-
|
|
409
|
-
// VM specification versions
|
|
410
|
-
this.vmSpecs = {
|
|
411
|
-
evm: '0.8.24', // Latest Solidity
|
|
412
|
-
svm: '1.18.0', // Latest Solana
|
|
413
|
-
move: '1.0.0', // Aptos Move
|
|
414
|
-
tvm: '4.0.0', // TON
|
|
415
|
-
cairo: '2.0.0', // Starknet Cairo
|
|
416
|
-
wasm: '3.0.0' // WASM 3.0
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
// Upgrade queue
|
|
420
|
-
this.upgradeQueue = [];
|
|
421
|
-
|
|
422
|
-
// Auto-upgrade enabled
|
|
423
|
-
this.autoUpgrade = true;
|
|
424
|
-
|
|
425
|
-
console.log('[DynamicContractManager] Initialized');
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
* Deploy a new dynamic contract
|
|
430
|
-
*/
|
|
431
|
-
async deploy(source, language, options = {}) {
|
|
432
|
-
const address = options.address || this.generateAddress(source);
|
|
433
|
-
|
|
434
|
-
console.log(`[DynamicContractManager] Deploying ${language} contract to ${address.substring(0, 16)}...`);
|
|
435
|
-
|
|
436
|
-
const contract = new DynamicContract(address, source, language);
|
|
437
|
-
|
|
438
|
-
// Initial compilation
|
|
439
|
-
await contract.compile(this.compiler);
|
|
440
|
-
|
|
441
|
-
// Register
|
|
442
|
-
this.contracts.set(address, contract);
|
|
443
|
-
|
|
444
|
-
// Setup event listeners
|
|
445
|
-
contract.on('dependentNeedsUpgrade', ({ dependent, reason }) => {
|
|
446
|
-
if (this.autoUpgrade) {
|
|
447
|
-
this.queueUpgrade(dependent, reason);
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
this.emit('deployed', { address, language, version: contract.version });
|
|
452
|
-
|
|
453
|
-
return {
|
|
454
|
-
address,
|
|
455
|
-
contract,
|
|
456
|
-
bytecode: contract.bytecode,
|
|
457
|
-
abi: contract.getABI()
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
/**
|
|
462
|
-
* Update VM specs (triggers auto-upgrade)
|
|
463
|
-
*/
|
|
464
|
-
async updateVMSpec(vm, newVersion) {
|
|
465
|
-
const oldVersion = this.vmSpecs[vm];
|
|
466
|
-
this.vmSpecs[vm] = newVersion;
|
|
467
|
-
|
|
468
|
-
console.log(`[DynamicContractManager] VM spec update: ${vm} ${oldVersion} → ${newVersion}`);
|
|
469
|
-
|
|
470
|
-
// Find all contracts using this VM
|
|
471
|
-
const affectedContracts = [];
|
|
472
|
-
for (const [address, contract] of this.contracts) {
|
|
473
|
-
// Fixed: was triple comparison bug (a === b === c)
|
|
474
|
-
if (this.languageToVM(contract.language) === vm) {
|
|
475
|
-
affectedContracts.push(address);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
console.log(`[DynamicContractManager] ${affectedContracts.length} contracts affected`);
|
|
480
|
-
|
|
481
|
-
if (this.autoUpgrade) {
|
|
482
|
-
// Queue all for upgrade
|
|
483
|
-
for (const address of affectedContracts) {
|
|
484
|
-
this.queueUpgrade(address, `vm-upgrade:${vm}:${newVersion}`);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// Process queue
|
|
488
|
-
await this.processUpgradeQueue();
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
return affectedContracts;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
languageToVM(language) {
|
|
495
|
-
const map = {
|
|
496
|
-
'solidity': 'evm',
|
|
497
|
-
'vyper': 'evm',
|
|
498
|
-
'rust': 'svm',
|
|
499
|
-
'move': 'move',
|
|
500
|
-
'func': 'tvm',
|
|
501
|
-
'cairo': 'cairo'
|
|
502
|
-
};
|
|
503
|
-
return map[language] || 'evm';
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
/**
|
|
507
|
-
* Queue a contract for upgrade
|
|
508
|
-
*/
|
|
509
|
-
queueUpgrade(address, reason) {
|
|
510
|
-
if (!this.upgradeQueue.find(u => u.address === address)) {
|
|
511
|
-
this.upgradeQueue.push({ address, reason, queuedAt: Date.now() });
|
|
512
|
-
console.log(`[DynamicContractManager] Queued upgrade: ${address.substring(0, 16)}... (${reason})`);
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* Process upgrade queue
|
|
518
|
-
*/
|
|
519
|
-
async processUpgradeQueue() {
|
|
520
|
-
console.log(`[DynamicContractManager] Processing ${this.upgradeQueue.length} upgrades...`);
|
|
521
|
-
|
|
522
|
-
const results = [];
|
|
523
|
-
|
|
524
|
-
while (this.upgradeQueue.length > 0) {
|
|
525
|
-
const { address, reason } = this.upgradeQueue.shift();
|
|
526
|
-
|
|
527
|
-
const contract = this.contracts.get(address);
|
|
528
|
-
if (!contract) continue;
|
|
529
|
-
|
|
530
|
-
try {
|
|
531
|
-
await contract.upgrade(this.compiler, reason);
|
|
532
|
-
results.push({ address, success: true, version: contract.version });
|
|
533
|
-
} catch (error) {
|
|
534
|
-
results.push({ address, success: false, error: error.message });
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
console.log(`[DynamicContractManager] Completed ${results.length} upgrades`);
|
|
539
|
-
return results;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Direct cross-contract call (NO BRIDGES!)
|
|
544
|
-
*/
|
|
545
|
-
async crossContractCall(fromAddress, toAddress, functionName, args) {
|
|
546
|
-
console.log(`[DynamicContractManager] Cross-call: ${fromAddress.substring(0, 10)}... → ${toAddress.substring(0, 10)}...::${functionName}`);
|
|
547
|
-
|
|
548
|
-
const fromContract = this.contracts.get(fromAddress);
|
|
549
|
-
const toContract = this.contracts.get(toAddress);
|
|
550
|
-
|
|
551
|
-
if (!fromContract || !toContract) {
|
|
552
|
-
throw new Error('Contract not found');
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// Get function from target contract
|
|
556
|
-
const func = toContract.interface.functions.get(functionName);
|
|
557
|
-
if (!func) {
|
|
558
|
-
throw new Error(`Function not found: ${functionName}`);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// Direct call - same memory space, no bridge!
|
|
562
|
-
// The key insight: both contracts share the same state store
|
|
563
|
-
// and can access each other's state directly
|
|
564
|
-
|
|
565
|
-
// Record dependency
|
|
566
|
-
fromContract.dependencies.add(toAddress);
|
|
567
|
-
toContract.dependents.add(fromAddress);
|
|
568
|
-
|
|
569
|
-
this.emit('crossCall', {
|
|
570
|
-
from: fromAddress,
|
|
571
|
-
to: toAddress,
|
|
572
|
-
function: functionName,
|
|
573
|
-
args
|
|
574
|
-
});
|
|
575
|
-
|
|
576
|
-
// Execute on target contract's bytecode
|
|
577
|
-
const result = await this.executeFunction(toContract, func, args, {
|
|
578
|
-
caller: fromAddress,
|
|
579
|
-
origin: fromAddress,
|
|
580
|
-
value: 0n
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
return result;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/**
|
|
587
|
-
* Execute a function on a contract
|
|
588
|
-
*
|
|
589
|
-
* This is the actual bytecode execution engine
|
|
590
|
-
*/
|
|
591
|
-
async executeFunction(contract, func, args, context = {}) {
|
|
592
|
-
// JIR Opcodes
|
|
593
|
-
const OP = {
|
|
594
|
-
NOP: 0x00, BLOCK: 0x01, LOOP: 0x02, IF: 0x03, ELSE: 0x04, END: 0x05,
|
|
595
|
-
BR: 0x06, BR_IF: 0x07, RETURN: 0x08, CALL: 0x09,
|
|
596
|
-
DROP: 0x10, LOCAL_GET: 0x12, LOCAL_SET: 0x13,
|
|
597
|
-
I32_LOAD: 0x20, I64_LOAD: 0x21, I32_STORE: 0x24, I64_STORE: 0x25,
|
|
598
|
-
I32_CONST: 0x30, I64_CONST: 0x31,
|
|
599
|
-
I32_ADD: 0x34, I32_SUB: 0x35, I32_MUL: 0x36, I32_DIV_S: 0x37,
|
|
600
|
-
I64_ADD: 0x39, I64_SUB: 0x3A, I64_MUL: 0x3B, I64_DIV_S: 0x3C,
|
|
601
|
-
I32_EQ: 0x40, I32_NE: 0x41, I32_LT_S: 0x42, I32_GT_S: 0x44,
|
|
602
|
-
I32_AND: 0x50, I32_OR: 0x51, I32_XOR: 0x52,
|
|
603
|
-
SLOAD: 0x80, SSTORE: 0x81, BALANCE: 0x84, TRANSFER: 0x85,
|
|
604
|
-
CONTRACT_CALL: 0x87, CALLER: 0x90, CALLVALUE: 0x92,
|
|
605
|
-
TIMESTAMP: 0xA2, BLOCKNUMBER: 0xA3,
|
|
606
|
-
LOG0: 0xC0, LOG1: 0xC1, LOG2: 0xC2, LOG3: 0xC3, LOG4: 0xC4,
|
|
607
|
-
CROSS_VM_CALL: 0xD0, REVERT: 0xFE, HALT: 0xFF
|
|
608
|
-
};
|
|
609
|
-
|
|
610
|
-
// Find function bytecode in contract
|
|
611
|
-
let funcBytecode = null;
|
|
612
|
-
|
|
613
|
-
// Search in compiled bytecode for the function
|
|
614
|
-
if (contract.bytecode) {
|
|
615
|
-
// Parse bytecode to find function by selector
|
|
616
|
-
const selector = func.selector;
|
|
617
|
-
const bytecode = contract.bytecode;
|
|
618
|
-
|
|
619
|
-
// Simple bytecode structure: look for matching selector
|
|
620
|
-
// Format: [magic][version][contracts...]
|
|
621
|
-
// Contract: [nameLen][name][funcCount][functions...]
|
|
622
|
-
// Function: [selector:4][bytecodeLen:2][bytecode...]
|
|
623
|
-
|
|
624
|
-
let pos = 11; // Skip magic (8) + version (3)
|
|
625
|
-
if (bytecode.length > pos) {
|
|
626
|
-
const contractCount = bytecode[pos++];
|
|
627
|
-
for (let c = 0; c < contractCount && !funcBytecode; c++) {
|
|
628
|
-
const nameLen = bytecode[pos++];
|
|
629
|
-
pos += nameLen; // Skip name
|
|
630
|
-
const funcCount = bytecode[pos++];
|
|
631
|
-
for (let f = 0; f < funcCount; f++) {
|
|
632
|
-
const funcSelector = bytecode.slice(pos, pos + 4);
|
|
633
|
-
pos += 4;
|
|
634
|
-
const bytecodeLen = bytecode.readUInt16LE(pos);
|
|
635
|
-
pos += 2;
|
|
636
|
-
if (selector.equals(funcSelector)) {
|
|
637
|
-
funcBytecode = bytecode.slice(pos, pos + bytecodeLen);
|
|
638
|
-
break;
|
|
639
|
-
}
|
|
640
|
-
pos += bytecodeLen;
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
if (!funcBytecode) {
|
|
647
|
-
// No bytecode found, return default
|
|
648
|
-
console.log(`[ExecuteFunction] No bytecode found for ${func.name}, using default`);
|
|
649
|
-
return {
|
|
650
|
-
success: true,
|
|
651
|
-
returnValue: null,
|
|
652
|
-
gasUsed: 0,
|
|
653
|
-
logs: []
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// Execute bytecode
|
|
658
|
-
const stack = [];
|
|
659
|
-
const locals = new Map();
|
|
660
|
-
const logs = [];
|
|
661
|
-
let pc = 0; // Program counter
|
|
662
|
-
let returnValue = null;
|
|
663
|
-
let reverted = false;
|
|
664
|
-
|
|
665
|
-
// Initialize locals with args
|
|
666
|
-
for (let i = 0; i < args.length; i++) {
|
|
667
|
-
locals.set(i, args[i]);
|
|
668
|
-
}
|
|
669
|
-
|
|
670
|
-
// Execution loop
|
|
671
|
-
while (pc < funcBytecode.length && !reverted) {
|
|
672
|
-
const opcode = funcBytecode[pc++];
|
|
673
|
-
|
|
674
|
-
switch (opcode) {
|
|
675
|
-
case OP.NOP:
|
|
676
|
-
break;
|
|
677
|
-
|
|
678
|
-
case OP.BLOCK:
|
|
679
|
-
// Skip param/return counts
|
|
680
|
-
pc += 2;
|
|
681
|
-
break;
|
|
682
|
-
|
|
683
|
-
case OP.END:
|
|
684
|
-
// End of block
|
|
685
|
-
break;
|
|
686
|
-
|
|
687
|
-
case OP.RETURN:
|
|
688
|
-
returnValue = stack.pop();
|
|
689
|
-
pc = funcBytecode.length; // Exit loop
|
|
690
|
-
break;
|
|
691
|
-
|
|
692
|
-
case OP.I32_CONST:
|
|
693
|
-
const i32 = funcBytecode.readInt32LE(pc);
|
|
694
|
-
pc += 4;
|
|
695
|
-
stack.push(i32);
|
|
696
|
-
break;
|
|
697
|
-
|
|
698
|
-
case OP.I64_CONST:
|
|
699
|
-
const i64 = funcBytecode.readBigInt64LE(pc);
|
|
700
|
-
pc += 8;
|
|
701
|
-
stack.push(i64);
|
|
702
|
-
break;
|
|
703
|
-
|
|
704
|
-
case OP.LOCAL_GET:
|
|
705
|
-
const getIdx = funcBytecode[pc++];
|
|
706
|
-
stack.push(locals.get(getIdx) || 0n);
|
|
707
|
-
break;
|
|
708
|
-
|
|
709
|
-
case OP.LOCAL_SET:
|
|
710
|
-
const setIdx = funcBytecode[pc++];
|
|
711
|
-
locals.set(setIdx, stack.pop());
|
|
712
|
-
break;
|
|
713
|
-
|
|
714
|
-
case OP.I64_ADD:
|
|
715
|
-
const addB = BigInt(stack.pop() || 0);
|
|
716
|
-
const addA = BigInt(stack.pop() || 0);
|
|
717
|
-
stack.push(addA + addB);
|
|
718
|
-
break;
|
|
719
|
-
|
|
720
|
-
case OP.I64_SUB:
|
|
721
|
-
const subB = BigInt(stack.pop() || 0);
|
|
722
|
-
const subA = BigInt(stack.pop() || 0);
|
|
723
|
-
stack.push(subA - subB);
|
|
724
|
-
break;
|
|
725
|
-
|
|
726
|
-
case OP.I64_MUL:
|
|
727
|
-
const mulB = BigInt(stack.pop() || 0);
|
|
728
|
-
const mulA = BigInt(stack.pop() || 0);
|
|
729
|
-
stack.push(mulA * mulB);
|
|
730
|
-
break;
|
|
731
|
-
|
|
732
|
-
case OP.I64_DIV_S:
|
|
733
|
-
const divB = BigInt(stack.pop() || 1);
|
|
734
|
-
const divA = BigInt(stack.pop() || 0);
|
|
735
|
-
stack.push(divB !== 0n ? divA / divB : 0n);
|
|
736
|
-
break;
|
|
737
|
-
|
|
738
|
-
case OP.I32_EQ:
|
|
739
|
-
const eqB = stack.pop();
|
|
740
|
-
const eqA = stack.pop();
|
|
741
|
-
stack.push(eqA === eqB ? 1 : 0);
|
|
742
|
-
break;
|
|
743
|
-
|
|
744
|
-
case OP.I32_NE:
|
|
745
|
-
const neB = stack.pop();
|
|
746
|
-
const neA = stack.pop();
|
|
747
|
-
stack.push(neA !== neB ? 1 : 0);
|
|
748
|
-
break;
|
|
749
|
-
|
|
750
|
-
case OP.I32_LT_S:
|
|
751
|
-
const ltB = stack.pop();
|
|
752
|
-
const ltA = stack.pop();
|
|
753
|
-
stack.push(ltA < ltB ? 1 : 0);
|
|
754
|
-
break;
|
|
755
|
-
|
|
756
|
-
case OP.I32_GT_S:
|
|
757
|
-
const gtB = stack.pop();
|
|
758
|
-
const gtA = stack.pop();
|
|
759
|
-
stack.push(gtA > gtB ? 1 : 0);
|
|
760
|
-
break;
|
|
761
|
-
|
|
762
|
-
case OP.IF:
|
|
763
|
-
const condition = stack.pop();
|
|
764
|
-
if (!condition) {
|
|
765
|
-
// Skip to ELSE or END
|
|
766
|
-
let depth = 1;
|
|
767
|
-
while (depth > 0 && pc < funcBytecode.length) {
|
|
768
|
-
const op = funcBytecode[pc++];
|
|
769
|
-
if (op === OP.IF || op === OP.BLOCK || op === OP.LOOP) depth++;
|
|
770
|
-
else if (op === OP.END) depth--;
|
|
771
|
-
else if (op === OP.ELSE && depth === 1) break;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
break;
|
|
775
|
-
|
|
776
|
-
case OP.ELSE:
|
|
777
|
-
// Skip to END (we executed the IF branch)
|
|
778
|
-
let elseDepth = 1;
|
|
779
|
-
while (elseDepth > 0 && pc < funcBytecode.length) {
|
|
780
|
-
const op = funcBytecode[pc++];
|
|
781
|
-
if (op === OP.IF || op === OP.BLOCK || op === OP.LOOP) elseDepth++;
|
|
782
|
-
else if (op === OP.END) elseDepth--;
|
|
783
|
-
}
|
|
784
|
-
break;
|
|
785
|
-
|
|
786
|
-
case OP.SLOAD:
|
|
787
|
-
// Load from storage
|
|
788
|
-
const loadSlot = stack.pop() || Buffer.alloc(32);
|
|
789
|
-
const slotBuf = typeof loadSlot === 'string'
|
|
790
|
-
? Buffer.from(loadSlot.replace('0x', ''), 'hex')
|
|
791
|
-
: Buffer.isBuffer(loadSlot) ? loadSlot : Buffer.alloc(32);
|
|
792
|
-
const loadValue = contract.state.read(slotBuf);
|
|
793
|
-
stack.push(loadValue.readBigUInt64LE(0));
|
|
794
|
-
break;
|
|
795
|
-
|
|
796
|
-
case OP.SSTORE:
|
|
797
|
-
// Store to storage
|
|
798
|
-
const storeValue = stack.pop();
|
|
799
|
-
const storeSlot = stack.pop() || Buffer.alloc(32);
|
|
800
|
-
const storeSlotBuf = typeof storeSlot === 'string'
|
|
801
|
-
? Buffer.from(storeSlot.replace('0x', ''), 'hex')
|
|
802
|
-
: Buffer.isBuffer(storeSlot) ? storeSlot : Buffer.alloc(32);
|
|
803
|
-
const valueBuf = Buffer.alloc(32);
|
|
804
|
-
if (typeof storeValue === 'bigint') {
|
|
805
|
-
for (let i = 0; i < 8; i++) {
|
|
806
|
-
valueBuf[i] = Number((storeValue >> BigInt(i * 8)) & 0xFFn);
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
contract.state.write(storeSlotBuf, valueBuf);
|
|
810
|
-
break;
|
|
811
|
-
|
|
812
|
-
case OP.CALLER:
|
|
813
|
-
stack.push(context.caller || '0x0000000000000000000000000000000000000000');
|
|
814
|
-
break;
|
|
815
|
-
|
|
816
|
-
case OP.CALLVALUE:
|
|
817
|
-
stack.push(context.value || 0n);
|
|
818
|
-
break;
|
|
819
|
-
|
|
820
|
-
case OP.TIMESTAMP:
|
|
821
|
-
stack.push(BigInt(Math.floor(Date.now() / 1000)));
|
|
822
|
-
break;
|
|
823
|
-
|
|
824
|
-
case OP.BLOCKNUMBER:
|
|
825
|
-
stack.push(BigInt(context.blockNumber || 0));
|
|
826
|
-
break;
|
|
827
|
-
|
|
828
|
-
case OP.LOG0:
|
|
829
|
-
case OP.LOG1:
|
|
830
|
-
case OP.LOG2:
|
|
831
|
-
case OP.LOG3:
|
|
832
|
-
case OP.LOG4:
|
|
833
|
-
const topicCount = opcode - OP.LOG0;
|
|
834
|
-
const topics = [];
|
|
835
|
-
for (let i = 0; i < topicCount; i++) {
|
|
836
|
-
topics.push(stack.pop());
|
|
837
|
-
}
|
|
838
|
-
const logData = stack.pop();
|
|
839
|
-
logs.push({ topics, data: logData });
|
|
840
|
-
break;
|
|
841
|
-
|
|
842
|
-
case OP.DROP:
|
|
843
|
-
stack.pop();
|
|
844
|
-
break;
|
|
845
|
-
|
|
846
|
-
case OP.REVERT:
|
|
847
|
-
reverted = true;
|
|
848
|
-
returnValue = stack.pop();
|
|
849
|
-
break;
|
|
850
|
-
|
|
851
|
-
case OP.HALT:
|
|
852
|
-
pc = funcBytecode.length;
|
|
853
|
-
break;
|
|
854
|
-
|
|
855
|
-
default:
|
|
856
|
-
// Skip unknown opcodes
|
|
857
|
-
break;
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
return {
|
|
862
|
-
success: !reverted,
|
|
863
|
-
returnValue: returnValue,
|
|
864
|
-
gasUsed: 0, // ZERO FEES!
|
|
865
|
-
logs: logs
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
/**
|
|
870
|
-
* Shared state access (between ANY contracts!)
|
|
871
|
-
*
|
|
872
|
-
* Access control rules:
|
|
873
|
-
* 1. A contract can always read/write its own state
|
|
874
|
-
* 2. Cross-contract state access requires explicit permission
|
|
875
|
-
* 3. Immutable slots cannot be modified after initial write
|
|
876
|
-
*/
|
|
877
|
-
async sharedStateRead(contractAddress, slot, callerAddress = null) {
|
|
878
|
-
const contract = this.contracts.get(contractAddress);
|
|
879
|
-
if (!contract) {
|
|
880
|
-
throw new Error('Contract not found');
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
// Self-access is always allowed
|
|
884
|
-
if (!callerAddress || callerAddress === contractAddress) {
|
|
885
|
-
return contract.state.read(slot);
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
// Cross-contract read: check permissions
|
|
889
|
-
const permissions = contract.statePermissions || new Map();
|
|
890
|
-
const slotKey = slot.toString('hex');
|
|
891
|
-
const slotPerms = permissions.get(slotKey) || { read: 'public', write: 'owner' };
|
|
892
|
-
|
|
893
|
-
if (slotPerms.read === 'public') {
|
|
894
|
-
return contract.state.read(slot);
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
if (slotPerms.read === 'allowlist') {
|
|
898
|
-
const allowedReaders = slotPerms.readers || new Set();
|
|
899
|
-
if (allowedReaders.has(callerAddress)) {
|
|
900
|
-
return contract.state.read(slot);
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
|
|
904
|
-
throw new Error(`Access denied: ${callerAddress} cannot read slot ${slotKey} from ${contractAddress}`);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
async sharedStateWrite(contractAddress, slot, value, callerAddress) {
|
|
908
|
-
const contract = this.contracts.get(contractAddress);
|
|
909
|
-
if (!contract) {
|
|
910
|
-
throw new Error('Contract not found');
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
// Initialize permissions map if not exists
|
|
914
|
-
if (!contract.statePermissions) {
|
|
915
|
-
contract.statePermissions = new Map();
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
const slotKey = slot.toString('hex');
|
|
919
|
-
const slotPerms = contract.statePermissions.get(slotKey) || { read: 'public', write: 'owner' };
|
|
920
|
-
|
|
921
|
-
// Check immutability
|
|
922
|
-
if (slotPerms.immutable) {
|
|
923
|
-
const existingValue = contract.state.read(slot);
|
|
924
|
-
const isZero = existingValue.every(b => b === 0);
|
|
925
|
-
if (!isZero) {
|
|
926
|
-
throw new Error(`Access denied: slot ${slotKey} is immutable and already set`);
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
// Self-access is always allowed
|
|
931
|
-
if (!callerAddress || callerAddress === contractAddress) {
|
|
932
|
-
return contract.state.write(slot, value);
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
// Cross-contract write: check permissions
|
|
936
|
-
if (slotPerms.write === 'owner') {
|
|
937
|
-
throw new Error(`Access denied: ${callerAddress} cannot write to slot ${slotKey} (owner-only)`);
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
if (slotPerms.write === 'allowlist') {
|
|
941
|
-
const allowedWriters = slotPerms.writers || new Set();
|
|
942
|
-
if (!allowedWriters.has(callerAddress)) {
|
|
943
|
-
throw new Error(`Access denied: ${callerAddress} not in write allowlist for slot ${slotKey}`);
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
// Write allowed
|
|
948
|
-
console.log(`[StateAccess] Cross-contract write: ${callerAddress.substring(0, 10)}... → ${contractAddress.substring(0, 10)}...`);
|
|
949
|
-
return contract.state.write(slot, value);
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
/**
|
|
953
|
-
* Set state permissions for a slot
|
|
954
|
-
*
|
|
955
|
-
* @param {string} contractAddress - Contract address
|
|
956
|
-
* @param {Buffer} slot - Storage slot
|
|
957
|
-
* @param {object} permissions - { read: 'public'|'owner'|'allowlist', write: 'owner'|'allowlist', immutable: boolean }
|
|
958
|
-
* @param {string} callerAddress - Caller must be contract owner
|
|
959
|
-
*/
|
|
960
|
-
async setStatePermissions(contractAddress, slot, permissions, callerAddress) {
|
|
961
|
-
const contract = this.contracts.get(contractAddress);
|
|
962
|
-
if (!contract) {
|
|
963
|
-
throw new Error('Contract not found');
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
// Only contract owner can set permissions
|
|
967
|
-
if (callerAddress !== contractAddress) {
|
|
968
|
-
throw new Error('Only contract owner can set state permissions');
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
if (!contract.statePermissions) {
|
|
972
|
-
contract.statePermissions = new Map();
|
|
973
|
-
}
|
|
974
|
-
|
|
975
|
-
const slotKey = slot.toString('hex');
|
|
976
|
-
const existing = contract.statePermissions.get(slotKey) || {};
|
|
977
|
-
|
|
978
|
-
contract.statePermissions.set(slotKey, {
|
|
979
|
-
read: permissions.read || existing.read || 'public',
|
|
980
|
-
write: permissions.write || existing.write || 'owner',
|
|
981
|
-
immutable: permissions.immutable || existing.immutable || false,
|
|
982
|
-
readers: permissions.readers || existing.readers || new Set(),
|
|
983
|
-
writers: permissions.writers || existing.writers || new Set()
|
|
984
|
-
});
|
|
985
|
-
|
|
986
|
-
console.log(`[StateAccess] Permissions updated for ${contractAddress.substring(0, 10)}...::${slotKey.substring(0, 16)}...`);
|
|
987
|
-
|
|
988
|
-
return true;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
/**
|
|
992
|
-
* Grant state access to another contract
|
|
993
|
-
*/
|
|
994
|
-
async grantStateAccess(contractAddress, slot, granteeAddress, accessType, callerAddress) {
|
|
995
|
-
const contract = this.contracts.get(contractAddress);
|
|
996
|
-
if (!contract) {
|
|
997
|
-
throw new Error('Contract not found');
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
if (callerAddress !== contractAddress) {
|
|
1001
|
-
throw new Error('Only contract owner can grant state access');
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
if (!contract.statePermissions) {
|
|
1005
|
-
contract.statePermissions = new Map();
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
const slotKey = slot.toString('hex');
|
|
1009
|
-
const perms = contract.statePermissions.get(slotKey) || {
|
|
1010
|
-
read: 'public',
|
|
1011
|
-
write: 'owner',
|
|
1012
|
-
readers: new Set(),
|
|
1013
|
-
writers: new Set()
|
|
1014
|
-
};
|
|
1015
|
-
|
|
1016
|
-
if (accessType === 'read') {
|
|
1017
|
-
perms.readers = perms.readers || new Set();
|
|
1018
|
-
perms.readers.add(granteeAddress);
|
|
1019
|
-
perms.read = 'allowlist';
|
|
1020
|
-
} else if (accessType === 'write') {
|
|
1021
|
-
perms.writers = perms.writers || new Set();
|
|
1022
|
-
perms.writers.add(granteeAddress);
|
|
1023
|
-
perms.write = 'allowlist';
|
|
1024
|
-
}
|
|
1025
|
-
|
|
1026
|
-
contract.statePermissions.set(slotKey, perms);
|
|
1027
|
-
|
|
1028
|
-
console.log(`[StateAccess] Granted ${accessType} access to ${granteeAddress.substring(0, 10)}... for ${slotKey.substring(0, 16)}...`);
|
|
1029
|
-
|
|
1030
|
-
return true;
|
|
1031
|
-
}
|
|
1032
|
-
|
|
1033
|
-
/**
|
|
1034
|
-
* Revoke state access from another contract
|
|
1035
|
-
*/
|
|
1036
|
-
async revokeStateAccess(contractAddress, slot, granteeAddress, accessType, callerAddress) {
|
|
1037
|
-
const contract = this.contracts.get(contractAddress);
|
|
1038
|
-
if (!contract) {
|
|
1039
|
-
throw new Error('Contract not found');
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
if (callerAddress !== contractAddress) {
|
|
1043
|
-
throw new Error('Only contract owner can revoke state access');
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
if (!contract.statePermissions) {
|
|
1047
|
-
return false;
|
|
1048
|
-
}
|
|
1049
|
-
|
|
1050
|
-
const slotKey = slot.toString('hex');
|
|
1051
|
-
const perms = contract.statePermissions.get(slotKey);
|
|
1052
|
-
if (!perms) {
|
|
1053
|
-
return false;
|
|
1054
|
-
}
|
|
1055
|
-
|
|
1056
|
-
if (accessType === 'read' && perms.readers) {
|
|
1057
|
-
perms.readers.delete(granteeAddress);
|
|
1058
|
-
} else if (accessType === 'write' && perms.writers) {
|
|
1059
|
-
perms.writers.delete(granteeAddress);
|
|
1060
|
-
}
|
|
1061
|
-
|
|
1062
|
-
contract.statePermissions.set(slotKey, perms);
|
|
1063
|
-
|
|
1064
|
-
console.log(`[StateAccess] Revoked ${accessType} access from ${granteeAddress.substring(0, 10)}... for ${slotKey.substring(0, 16)}...`);
|
|
1065
|
-
|
|
1066
|
-
return true;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
/**
|
|
1070
|
-
* Generate deterministic address
|
|
1071
|
-
*/
|
|
1072
|
-
generateAddress(source) {
|
|
1073
|
-
const hash = crypto.createHash('sha256')
|
|
1074
|
-
.update(source + Date.now())
|
|
1075
|
-
.digest('hex');
|
|
1076
|
-
return '0x' + hash.substring(0, 40);
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
/**
|
|
1080
|
-
* Get all contracts
|
|
1081
|
-
*/
|
|
1082
|
-
getAllContracts() {
|
|
1083
|
-
return Array.from(this.contracts.entries()).map(([address, contract]) => ({
|
|
1084
|
-
address,
|
|
1085
|
-
language: contract.language,
|
|
1086
|
-
version: contract.version,
|
|
1087
|
-
lastCompiled: contract.lastCompiled,
|
|
1088
|
-
functions: contract.interface.functions.size,
|
|
1089
|
-
dependencies: contract.dependencies.size,
|
|
1090
|
-
dependents: contract.dependents.size
|
|
1091
|
-
}));
|
|
1092
|
-
}
|
|
1093
|
-
|
|
1094
|
-
/**
|
|
1095
|
-
* Get contract dependency graph
|
|
1096
|
-
*/
|
|
1097
|
-
getDependencyGraph() {
|
|
1098
|
-
const graph = {
|
|
1099
|
-
nodes: [],
|
|
1100
|
-
edges: []
|
|
1101
|
-
};
|
|
1102
|
-
|
|
1103
|
-
for (const [address, contract] of this.contracts) {
|
|
1104
|
-
graph.nodes.push({
|
|
1105
|
-
id: address,
|
|
1106
|
-
language: contract.language,
|
|
1107
|
-
version: contract.version
|
|
1108
|
-
});
|
|
1109
|
-
|
|
1110
|
-
for (const dep of contract.dependencies) {
|
|
1111
|
-
graph.edges.push({
|
|
1112
|
-
from: address,
|
|
1113
|
-
to: dep,
|
|
1114
|
-
type: 'depends-on'
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
|
|
1119
|
-
return graph;
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
module.exports = {
|
|
1124
|
-
DynamicContract,
|
|
1125
|
-
DynamicContractManager,
|
|
1126
|
-
ContractStateStore
|
|
1127
|
-
};
|