jaelis-node 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/lib/index.js +444 -23
  2. package/lib/vm/index.js +397 -0
  3. package/package.json +12 -3
package/lib/index.js CHANGED
@@ -362,14 +362,26 @@ class BootstrapNode extends EventEmitter {
362
362
  }
363
363
 
364
364
  // ============================================================
365
- // EMBEDDED MINIMAL IMPLEMENTATIONS (for standalone operation)
365
+ // EMBEDDED IMPLEMENTATIONS WITH UNIFIED VM
366
366
  // ============================================================
367
367
 
368
+ // Import VM Executor (UnifiedJaelisVM integration)
369
+ let VMExecutor;
370
+ try {
371
+ VMExecutor = require('./vm').VMExecutor;
372
+ } catch (e) {
373
+ console.log('[JAELIS] VM module not loaded - running in light mode');
374
+ }
375
+
368
376
  class EmbeddedBlockchain {
369
377
  constructor(options = {}) {
370
378
  this.chainId = options.chainId || 4545;
371
379
  this.chain = [];
372
380
  this.state = new Map();
381
+ this.pendingTransactions = [];
382
+
383
+ // Initialize VM Executor (UnifiedJaelisVM - NO BRIDGES!)
384
+ this.vmExecutor = null;
373
385
  }
374
386
 
375
387
  async initialize() {
@@ -378,18 +390,139 @@ class EmbeddedBlockchain {
378
390
  this.chain.push({
379
391
  number: 0,
380
392
  hash: '0x' + '0'.repeat(64),
393
+ parentHash: '0x' + '0'.repeat(64),
381
394
  timestamp: Date.now(),
382
- transactions: []
395
+ transactions: [],
396
+ stateRoot: '0x' + '0'.repeat(64)
383
397
  });
384
398
  }
399
+
400
+ // Initialize the Unified VM
401
+ if (VMExecutor) {
402
+ this.vmExecutor = new VMExecutor(this, {
403
+ debug: false
404
+ });
405
+ console.log('[BLOCKCHAIN] Unified VM initialized - TRUE cross-chain interop!');
406
+ }
385
407
  }
386
408
 
387
409
  getHeight() {
388
410
  return this.chain.length - 1;
389
411
  }
390
412
 
413
+ getLatestBlock() {
414
+ return this.chain[this.chain.length - 1];
415
+ }
416
+
417
+ getBlock(numberOrHash) {
418
+ if (typeof numberOrHash === 'number') {
419
+ return this.chain[numberOrHash];
420
+ }
421
+ return this.chain.find(b => b.hash === numberOrHash);
422
+ }
423
+
424
+ /**
425
+ * Deploy a smart contract (ANY language!)
426
+ */
427
+ async deployContract(source, language, options = {}) {
428
+ if (!this.vmExecutor) {
429
+ throw new Error('VM not available - initialize blockchain first');
430
+ }
431
+ return this.vmExecutor.deployContract(source, language, options);
432
+ }
433
+
434
+ /**
435
+ * Execute a contract call
436
+ */
437
+ async executeContract(to, functionName, args = [], options = {}) {
438
+ if (!this.vmExecutor) {
439
+ throw new Error('VM not available');
440
+ }
441
+ return this.vmExecutor.executeCall(to, functionName, args, options);
442
+ }
443
+
444
+ /**
445
+ * Cross-contract call (NO BRIDGES!)
446
+ */
447
+ async crossContractCall(from, to, functionName, args = []) {
448
+ if (!this.vmExecutor) {
449
+ throw new Error('VM not available');
450
+ }
451
+ return this.vmExecutor.crossContractCall(from, to, functionName, args);
452
+ }
453
+
454
+ /**
455
+ * Process a transaction
456
+ */
457
+ async processTransaction(tx) {
458
+ if (this.vmExecutor) {
459
+ return this.vmExecutor.processTransaction(tx);
460
+ }
461
+ // Fallback: just store in pending
462
+ this.pendingTransactions.push(tx);
463
+ return { status: 'pending' };
464
+ }
465
+
466
+ /**
467
+ * Create a new block with pending transactions
468
+ */
469
+ async createBlock(validator) {
470
+ const crypto = require('crypto');
471
+ const parentBlock = this.getLatestBlock();
472
+
473
+ const block = {
474
+ number: parentBlock.number + 1,
475
+ hash: null,
476
+ parentHash: parentBlock.hash,
477
+ timestamp: Date.now(),
478
+ validator: validator || '0x0',
479
+ transactions: [...this.pendingTransactions],
480
+ stateRoot: this._computeStateRoot(),
481
+ gasUsed: 0 // ZERO FEES!
482
+ };
483
+
484
+ // Compute block hash
485
+ block.hash = '0x' + crypto.createHash('sha256')
486
+ .update(JSON.stringify({
487
+ number: block.number,
488
+ parentHash: block.parentHash,
489
+ timestamp: block.timestamp,
490
+ stateRoot: block.stateRoot
491
+ }))
492
+ .digest('hex');
493
+
494
+ // Add to chain
495
+ this.chain.push(block);
496
+ this.pendingTransactions = [];
497
+
498
+ console.log(`[BLOCKCHAIN] Block #${block.number} created with ${block.transactions.length} txs`);
499
+
500
+ return block;
501
+ }
502
+
503
+ _computeStateRoot() {
504
+ const crypto = require('crypto');
505
+ const stateData = JSON.stringify(Array.from(this.state.entries()));
506
+ return '0x' + crypto.createHash('sha256').update(stateData).digest('hex');
507
+ }
508
+
509
+ /**
510
+ * Get VM stats
511
+ */
512
+ getVMStats() {
513
+ return this.vmExecutor?.getStats?.() || { vmAvailable: false };
514
+ }
515
+
516
+ /**
517
+ * Get all deployed contracts
518
+ */
519
+ getContracts() {
520
+ return this.vmExecutor?.getAllContracts?.() || [];
521
+ }
522
+
391
523
  async save() {
392
- // Minimal save
524
+ // Save blockchain state to disk
525
+ // TODO: Implement persistent storage
393
526
  }
394
527
  }
395
528
 
@@ -529,34 +662,44 @@ class EmbeddedRpcServer {
529
662
 
530
663
  this.app = express();
531
664
  this.app.use(cors());
532
- this.app.use(express.json());
665
+ this.app.use(express.json({ limit: '50mb' })); // Allow large contract deployments
533
666
 
534
- // Basic RPC endpoint
535
- this.app.post('/', (req, res) => {
667
+ // Main RPC endpoint
668
+ this.app.post('/', async (req, res) => {
536
669
  const { method, params, id } = req.body;
537
670
 
538
- let result = null;
539
- let error = null;
540
-
541
- switch (method) {
542
- case 'jaelis_getHealth':
543
- case 'eth_chainId':
544
- result = { status: 'healthy', chainId: this.blockchain?.chainId };
545
- break;
546
- case 'jaelis_blockNumber':
547
- case 'eth_blockNumber':
548
- result = '0x' + (this.blockchain?.getHeight?.() || 0).toString(16);
549
- break;
550
- default:
551
- error = { code: -32601, message: 'Method not found' };
671
+ try {
672
+ const result = await this._handleMethod(method, params || []);
673
+ res.json({ jsonrpc: '2.0', id, result });
674
+ } catch (error) {
675
+ res.json({
676
+ jsonrpc: '2.0',
677
+ id,
678
+ error: { code: -32000, message: error.message }
679
+ });
552
680
  }
553
-
554
- res.json({ jsonrpc: '2.0', id, result, error });
555
681
  });
556
682
 
557
683
  // Health check
558
684
  this.app.get('/', (req, res) => {
559
- res.json({ status: 'online', service: 'JAELIS Node', chainId: this.blockchain?.chainId });
685
+ const vmStats = this.blockchain?.getVMStats?.() || {};
686
+ res.json({
687
+ status: 'online',
688
+ service: 'JAELIS Node',
689
+ chainId: this.blockchain?.chainId,
690
+ blockHeight: this.blockchain?.getHeight?.() || 0,
691
+ vm: {
692
+ available: vmStats.vmAvailable || false,
693
+ contractsDeployed: vmStats.contractsDeployed || 0,
694
+ crossContractCalls: vmStats.crossContractCalls || 0
695
+ },
696
+ features: [
697
+ 'ZERO_FEES',
698
+ 'UNIFIED_VM',
699
+ 'NO_BRIDGES',
700
+ 'CROSS_CHAIN_INTEROP'
701
+ ]
702
+ });
560
703
  });
561
704
 
562
705
  return new Promise((resolve) => {
@@ -566,6 +709,284 @@ class EmbeddedRpcServer {
566
709
  });
567
710
  }
568
711
 
712
+ async _handleMethod(method, params) {
713
+ switch (method) {
714
+ // ═══════════════════════════════════════════════════════════════
715
+ // STANDARD ETHEREUM-COMPATIBLE METHODS
716
+ // ═══════════════════════════════════════════════════════════════
717
+ case 'eth_chainId':
718
+ return '0x' + (this.blockchain?.chainId || 4545).toString(16);
719
+
720
+ case 'eth_blockNumber':
721
+ case 'jaelis_blockNumber':
722
+ return '0x' + (this.blockchain?.getHeight?.() || 0).toString(16);
723
+
724
+ case 'eth_getBlockByNumber':
725
+ const blockNum = parseInt(params[0], 16);
726
+ return this.blockchain?.getBlock?.(blockNum) || null;
727
+
728
+ case 'eth_sendTransaction':
729
+ case 'eth_sendRawTransaction':
730
+ return this._sendTransaction(params[0]);
731
+
732
+ case 'eth_call':
733
+ return this._call(params[0], params[1]);
734
+
735
+ case 'eth_getTransactionReceipt':
736
+ return this.blockchain?.vmExecutor?.getReceipt?.(params[0]) || null;
737
+
738
+ // ═══════════════════════════════════════════════════════════════
739
+ // JAELIS-SPECIFIC METHODS (Unified VM)
740
+ // ═══════════════════════════════════════════════════════════════
741
+ case 'jaelis_getHealth':
742
+ return {
743
+ status: 'healthy',
744
+ chainId: this.blockchain?.chainId,
745
+ blockHeight: this.blockchain?.getHeight?.() || 0,
746
+ vmActive: !!this.blockchain?.vmExecutor
747
+ };
748
+
749
+ case 'jaelis_deployContract':
750
+ // Deploy contract in ANY language!
751
+ // params: [source, language, options]
752
+ return this._deployContract(params[0], params[1], params[2] || {});
753
+
754
+ case 'jaelis_executeContract':
755
+ // Execute contract call
756
+ // params: [to, functionName, args, options]
757
+ return this._executeContract(params[0], params[1], params[2] || [], params[3] || {});
758
+
759
+ case 'jaelis_crossContractCall':
760
+ // Cross-contract call (NO BRIDGES!)
761
+ // params: [fromContract, toContract, functionName, args]
762
+ return this._crossContractCall(params[0], params[1], params[2], params[3] || []);
763
+
764
+ case 'jaelis_getContracts':
765
+ return this.blockchain?.getContracts?.() || [];
766
+
767
+ case 'jaelis_getVMStats':
768
+ return this.blockchain?.getVMStats?.() || { vmAvailable: false };
769
+
770
+ case 'jaelis_getSupportedLanguages':
771
+ return ['solidity', 'rust', 'move', 'func', 'cairo', 'vyper'];
772
+
773
+ // ═══════════════════════════════════════════════════════════════
774
+ // CROSS-CHAIN SETTLEMENT METHODS (Universal State Layer!)
775
+ // ═══════════════════════════════════════════════════════════════
776
+
777
+ case 'jaelis_crossChain_getChains':
778
+ // Get all registered chains
779
+ return this._getCrossChainRegistry();
780
+
781
+ case 'jaelis_crossChain_getChainInfo':
782
+ // Get info for specific chain ID
783
+ return this._getCrossChainInfo(params[0]);
784
+
785
+ case 'jaelis_crossChain_readState':
786
+ // Read settled state from external chain
787
+ // params: [chainId, contractAddress, variableName]
788
+ return this._readCrossChainState(params[0], params[1], params[2]);
789
+
790
+ case 'jaelis_crossChain_settleState':
791
+ // Settle external chain state with proof
792
+ // params: [chainId, contractAddress, variableName, value, proof]
793
+ return this._settleCrossChainState(params[0], params[1], params[2], params[3], params[4]);
794
+
795
+ case 'jaelis_crossChain_getStateDiff':
796
+ // Get state diff between two chains
797
+ // params: [chainId1, chainId2, contractAddress, variableNames]
798
+ return this._getCrossChainStateDiff(params[0], params[1], params[2], params[3]);
799
+
800
+ case 'jaelis_crossChain_computeSlot':
801
+ // Compute namespaced storage slot
802
+ // params: [chainId, contractAddress, variableName]
803
+ return this._computeCrossChainSlot(params[0], params[1], params[2]);
804
+
805
+ case 'jaelis_crossChain_getLightClientStatus':
806
+ // Get light client status for a chain
807
+ return this._getLightClientStatus(params[0]);
808
+
809
+ case 'jaelis_crossChain_getSettlements':
810
+ // Get all settlements for a contract
811
+ // params: [chainId, contractAddress]
812
+ return this._getSettlements(params[0], params[1]);
813
+
814
+ case 'jaelis_crossChain_getStats':
815
+ // Get cross-chain stats
816
+ return this._getCrossChainStats();
817
+
818
+ default:
819
+ throw new Error(`Method not found: ${method}`);
820
+ }
821
+ }
822
+
823
+ async _sendTransaction(tx) {
824
+ if (!this.blockchain) throw new Error('Blockchain not available');
825
+ const result = await this.blockchain.processTransaction(tx);
826
+ return result.transactionHash || '0x0';
827
+ }
828
+
829
+ async _call(callObject) {
830
+ if (!this.blockchain?.vmExecutor) throw new Error('VM not available');
831
+ const result = await this.blockchain.vmExecutor.executeCall(
832
+ callObject.to,
833
+ callObject.data?.functionName || 'call',
834
+ callObject.data?.args || [],
835
+ { from: callObject.from }
836
+ );
837
+ return result.returnValue;
838
+ }
839
+
840
+ async _deployContract(source, language, options) {
841
+ if (!this.blockchain) throw new Error('Blockchain not available');
842
+ console.log(`[RPC] Deploying ${language} contract...`);
843
+ const result = await this.blockchain.deployContract(source, language, options);
844
+ return {
845
+ address: result.address,
846
+ language,
847
+ gasUsed: 0 // ZERO FEES!
848
+ };
849
+ }
850
+
851
+ async _executeContract(to, functionName, args, options) {
852
+ if (!this.blockchain) throw new Error('Blockchain not available');
853
+ return this.blockchain.executeContract(to, functionName, args, options);
854
+ }
855
+
856
+ async _crossContractCall(from, to, functionName, args) {
857
+ if (!this.blockchain) throw new Error('Blockchain not available');
858
+ console.log(`[RPC] Cross-call: ${from.substring(0, 10)}... → ${to.substring(0, 10)}...::${functionName}`);
859
+ return this.blockchain.crossContractCall(from, to, functionName, args);
860
+ }
861
+
862
+ // ═══════════════════════════════════════════════════════════════
863
+ // CROSS-CHAIN SETTLEMENT IMPLEMENTATIONS
864
+ // ═══════════════════════════════════════════════════════════════
865
+
866
+ _getCrossChainRegistry() {
867
+ // Return the VM's cross-chain registry if available
868
+ if (this.blockchain?.vmExecutor?.vm?.getAllChains) {
869
+ return this.blockchain.vmExecutor.vm.getAllChains();
870
+ }
871
+ // Fallback: return hardcoded registry
872
+ return {
873
+ JAELIS_MAINNET: { id: 4547, name: 'JAELIS Mainnet', type: 'native', status: 'upcoming' },
874
+ JAELIS_TESTNET: { id: 4545, name: 'JAELIS Testnet', type: 'native', status: 'live' },
875
+ ETH_MAINNET: { id: 1, name: 'Ethereum Mainnet', type: 'evm' },
876
+ ETH_SEPOLIA: { id: 11155111, name: 'Ethereum Sepolia', type: 'evm' },
877
+ POLYGON: { id: 137, name: 'Polygon PoS', type: 'evm' },
878
+ ARBITRUM_ONE: { id: 42161, name: 'Arbitrum One', type: 'evm' },
879
+ OPTIMISM: { id: 10, name: 'OP Mainnet', type: 'evm' },
880
+ BASE: { id: 8453, name: 'Base', type: 'evm' },
881
+ AVALANCHE_C: { id: 43114, name: 'Avalanche C-Chain', type: 'evm' },
882
+ BSC: { id: 56, name: 'BNB Smart Chain', type: 'evm' },
883
+ SOLANA_MAINNET: { id: 101, name: 'Solana Mainnet', type: 'svm', cluster: 'mainnet-beta' },
884
+ SOLANA_DEVNET: { id: 102, name: 'Solana Devnet', type: 'svm', cluster: 'devnet' },
885
+ APTOS_MAINNET: { id: 1, name: 'Aptos Mainnet', type: 'move', network: 'aptos' },
886
+ SUI_MAINNET: { id: 1, name: 'Sui Mainnet', type: 'move', network: 'sui' },
887
+ TON_MAINNET: { id: -1, name: 'TON Mainnet', type: 'tvm', workchain: -1 }
888
+ };
889
+ }
890
+
891
+ _getCrossChainInfo(chainId) {
892
+ const chains = this._getCrossChainRegistry();
893
+ const chain = Object.values(chains).find(c => c.id === chainId);
894
+ return chain || { error: 'Chain not found', chainId };
895
+ }
896
+
897
+ async _readCrossChainState(chainId, contractAddress, variableName) {
898
+ if (this.blockchain?.vmExecutor?.vm?.readCrossChainState) {
899
+ const value = this.blockchain.vmExecutor.vm.readCrossChainState(chainId, contractAddress, variableName);
900
+ return {
901
+ chainId,
902
+ contractAddress,
903
+ variableName,
904
+ value: value ? '0x' + value.toString('hex') : '0x0',
905
+ settled: value ? true : false
906
+ };
907
+ }
908
+ return { error: 'Cross-chain state not available', chainId, contractAddress, variableName };
909
+ }
910
+
911
+ async _settleCrossChainState(chainId, contractAddress, variableName, value, proof) {
912
+ if (this.blockchain?.vmExecutor?.vm?.settleExternalState) {
913
+ const valueBuffer = Buffer.from(value.replace('0x', ''), 'hex');
914
+ const result = await this.blockchain.vmExecutor.vm.settleExternalState(
915
+ chainId, contractAddress, variableName, valueBuffer, proof
916
+ );
917
+ console.log(`[RPC] Cross-chain settlement: Chain ${chainId} → ${variableName}`);
918
+ return {
919
+ success: true,
920
+ chainId,
921
+ contractAddress,
922
+ variableName,
923
+ slot: result.slot ? '0x' + result.slot.toString('hex') : null,
924
+ settlement: result.settlement
925
+ };
926
+ }
927
+ return { error: 'Cross-chain settlement not available' };
928
+ }
929
+
930
+ _getCrossChainStateDiff(chainId1, chainId2, contractAddress, variableNames) {
931
+ if (this.blockchain?.vmExecutor?.vm?.getCrossChainStateDiff) {
932
+ return this.blockchain.vmExecutor.vm.getCrossChainStateDiff(
933
+ chainId1, chainId2, contractAddress, variableNames
934
+ );
935
+ }
936
+ return { error: 'State diff not available', chainId1, chainId2 };
937
+ }
938
+
939
+ _computeCrossChainSlot(chainId, contractAddress, variableName) {
940
+ if (this.blockchain?.vmExecutor?.vm?.computeCrossChainSlot) {
941
+ const slot = this.blockchain.vmExecutor.vm.computeCrossChainSlot(chainId, contractAddress, variableName);
942
+ return '0x' + slot.toString('hex');
943
+ }
944
+ // Fallback: compute locally
945
+ const crypto = require('crypto');
946
+ const data = Buffer.concat([
947
+ Buffer.alloc(4), // chainId placeholder
948
+ Buffer.from(contractAddress.replace('0x', ''), 'hex'),
949
+ Buffer.from(variableName, 'utf8')
950
+ ]);
951
+ data.writeUInt32LE(chainId, 0);
952
+ return '0x' + crypto.createHash('sha256').update(data).digest('hex');
953
+ }
954
+
955
+ _getLightClientStatus(chainId) {
956
+ if (this.blockchain?.vmExecutor?.vm?.crossChainManager?.stateStore?.lightClients) {
957
+ const client = this.blockchain.vmExecutor.vm.crossChainManager.stateStore.lightClients.get(chainId);
958
+ if (client) {
959
+ return {
960
+ chainId,
961
+ synced: client.synced || false,
962
+ latestBlock: client.latestBlock || 0,
963
+ stateRoot: client.latestStateRoot ? '0x' + client.latestStateRoot.toString('hex') : null
964
+ };
965
+ }
966
+ }
967
+ return { chainId, synced: false, error: 'Light client not available' };
968
+ }
969
+
970
+ _getSettlements(chainId, contractAddress) {
971
+ if (this.blockchain?.vmExecutor?.vm?.crossChainManager?.stateStore?.settlementLog) {
972
+ const log = this.blockchain.vmExecutor.vm.crossChainManager.stateStore.settlementLog;
973
+ return log.filter(s => s.chainId === chainId && s.contractAddress === contractAddress);
974
+ }
975
+ return [];
976
+ }
977
+
978
+ _getCrossChainStats() {
979
+ if (this.blockchain?.vmExecutor?.vm?.crossChainManager?.getStats) {
980
+ return this.blockchain.vmExecutor.vm.crossChainManager.getStats();
981
+ }
982
+ return {
983
+ totalSettlements: 0,
984
+ chainsActive: 0,
985
+ lightClientsRegistered: 0,
986
+ stateSize: 0
987
+ };
988
+ }
989
+
569
990
  async stop() {
570
991
  if (this.server) {
571
992
  this.server.close();
@@ -0,0 +1,397 @@
1
+ /**
2
+ * JAELIS UNIFIED VM INTEGRATION
3
+ *
4
+ * Wires the UnifiedJaelisVM (NO BRIDGES, NO ADAPTERS!) into the JAELIS blockchain
5
+ * for smart contract execution.
6
+ *
7
+ * This is THE execution engine - all contracts from ALL languages run here:
8
+ * - Solidity (EVM)
9
+ * - Rust (Solana)
10
+ * - Move (Aptos/Sui)
11
+ * - FunC (TON)
12
+ * - Cairo (Starknet)
13
+ *
14
+ * Key Features:
15
+ * - TRUE cross-chain interoperability (NO BRIDGES!)
16
+ * - Dynamic contracts (auto-update when VMs change)
17
+ * - JAELIS ABI (ONE encoding for all)
18
+ * - ZERO FEES (ENE system)
19
+ *
20
+ * @version 1.0.0
21
+ * @author Mario Papaleo - JAELIS Foundation
22
+ * @patent PATENT PENDING - Unified Cross-Chain Virtual Machine
23
+ */
24
+
25
+ const path = require('path');
26
+ const EventEmitter = require('events');
27
+
28
+ // Import the Unified VM from JAELIS-VM
29
+ let UnifiedJaelisVM, JaelisABI, DynamicContractManager;
30
+
31
+ try {
32
+ const vmPath = path.resolve(__dirname, '../../../JAELIS-VM/lib/unified');
33
+ const unified = require(vmPath);
34
+ UnifiedJaelisVM = unified.UnifiedJaelisVM;
35
+ JaelisABI = unified.JaelisABI;
36
+ DynamicContractManager = unified.DynamicContractManager;
37
+ } catch (e) {
38
+ console.warn('[JAELIS-VM] Could not load UnifiedJaelisVM from relative path, trying npm...');
39
+ try {
40
+ const unified = require('jaelis-vm/lib/unified');
41
+ UnifiedJaelisVM = unified.UnifiedJaelisVM;
42
+ JaelisABI = unified.JaelisABI;
43
+ DynamicContractManager = unified.DynamicContractManager;
44
+ } catch (e2) {
45
+ console.warn('[JAELIS-VM] UnifiedJaelisVM not available, using fallback');
46
+ }
47
+ }
48
+
49
+ /**
50
+ * VMExecutor - Executes smart contracts on the JAELIS blockchain
51
+ *
52
+ * This wraps the UnifiedJaelisVM and provides blockchain-specific functionality:
53
+ * - Transaction processing
54
+ * - State commitment to blockchain
55
+ * - Event emission for block inclusion
56
+ * - Gas-less execution (ENE system)
57
+ */
58
+ class VMExecutor extends EventEmitter {
59
+ constructor(blockchain, options = {}) {
60
+ super();
61
+
62
+ this.blockchain = blockchain;
63
+ this.options = options;
64
+
65
+ // Initialize the Unified VM (NO BRIDGES!)
66
+ if (UnifiedJaelisVM) {
67
+ this.vm = new UnifiedJaelisVM({
68
+ ...options,
69
+ enableLogging: options.debug || false
70
+ });
71
+ console.log('[VMExecutor] Unified VM initialized - NO BRIDGES, NO ADAPTERS!');
72
+ } else {
73
+ this.vm = null;
74
+ console.log('[VMExecutor] Running in light mode (no VM)');
75
+ }
76
+
77
+ // Contract address mapping
78
+ this.contracts = new Map();
79
+
80
+ // Pending state changes (committed on block finalization)
81
+ this.pendingStateChanges = [];
82
+
83
+ // Transaction receipts
84
+ this.receipts = new Map();
85
+
86
+ // Stats
87
+ this.stats = {
88
+ contractsDeployed: 0,
89
+ transactionsExecuted: 0,
90
+ crossContractCalls: 0,
91
+ totalGasUsed: 0 // Always 0 - ZERO FEES!
92
+ };
93
+ }
94
+
95
+ /**
96
+ * Deploy a smart contract
97
+ *
98
+ * Supports ANY language:
99
+ * - Solidity, Vyper (EVM)
100
+ * - Rust/Anchor (Solana)
101
+ * - Move (Aptos/Sui)
102
+ * - FunC (TON)
103
+ * - Cairo (Starknet)
104
+ */
105
+ async deployContract(source, language, options = {}) {
106
+ if (!this.vm) {
107
+ throw new Error('VM not available - run in full node mode');
108
+ }
109
+
110
+ const deployer = options.from || options.deployer || '0x0';
111
+
112
+ console.log(`[VMExecutor] Deploying ${language} contract...`);
113
+
114
+ // Deploy through Unified VM
115
+ const result = await this.vm.deploy(source, language, {
116
+ ...options,
117
+ deployer
118
+ });
119
+
120
+ // Store in local registry
121
+ this.contracts.set(result.address, {
122
+ address: result.address,
123
+ language,
124
+ deployedAt: Date.now(),
125
+ deployer,
126
+ bytecodeHash: result.bytecode ?
127
+ require('crypto').createHash('sha256').update(result.bytecode).digest('hex') : null
128
+ });
129
+
130
+ this.stats.contractsDeployed++;
131
+
132
+ // Emit event for block inclusion
133
+ this.emit('contractDeployed', {
134
+ address: result.address,
135
+ language,
136
+ deployer,
137
+ blockNumber: this.blockchain?.getHeight?.() || 0
138
+ });
139
+
140
+ console.log(`[VMExecutor] Contract deployed: ${result.address.substring(0, 20)}...`);
141
+
142
+ return {
143
+ address: result.address,
144
+ abi: result.abi,
145
+ language,
146
+ gasUsed: 0 // ZERO FEES!
147
+ };
148
+ }
149
+
150
+ /**
151
+ * Execute a contract call
152
+ */
153
+ async executeCall(to, functionName, args = [], options = {}) {
154
+ if (!this.vm) {
155
+ throw new Error('VM not available');
156
+ }
157
+
158
+ const from = options.from || '0x0';
159
+ const value = options.value || 0;
160
+
161
+ console.log(`[VMExecutor] Executing ${functionName} on ${to.substring(0, 16)}...`);
162
+
163
+ // Execute through Unified VM
164
+ const result = await this.vm.execute(to, functionName, args, {
165
+ from,
166
+ value,
167
+ blockNumber: this.blockchain?.getHeight?.() || 0,
168
+ timestamp: Date.now()
169
+ });
170
+
171
+ this.stats.transactionsExecuted++;
172
+
173
+ // Create receipt
174
+ const receipt = {
175
+ transactionHash: this._generateTxHash(to, functionName, args, from),
176
+ blockNumber: this.blockchain?.getHeight?.() || 0,
177
+ from,
178
+ to,
179
+ status: result.success ? 1 : 0,
180
+ gasUsed: 0, // ZERO FEES!
181
+ logs: result.logs || [],
182
+ returnValue: result.returnValue
183
+ };
184
+
185
+ this.receipts.set(receipt.transactionHash, receipt);
186
+
187
+ // Emit for block inclusion
188
+ this.emit('transactionExecuted', receipt);
189
+
190
+ return receipt;
191
+ }
192
+
193
+ /**
194
+ * Cross-contract call (NO BRIDGES!)
195
+ *
196
+ * This is THE key innovation - contracts from ANY VM can call each other DIRECTLY
197
+ */
198
+ async crossContractCall(fromContract, toContract, functionName, args = [], options = {}) {
199
+ if (!this.vm) {
200
+ throw new Error('VM not available');
201
+ }
202
+
203
+ console.log(`[VMExecutor] Cross-call: ${fromContract.substring(0, 10)}... → ${toContract.substring(0, 10)}...::${functionName}`);
204
+ console.log(`[VMExecutor] NO BRIDGE! NO ADAPTER! Direct execution.`);
205
+
206
+ // Execute through Unified VM's cross-call
207
+ const result = await this.vm.crossCall(fromContract, toContract, functionName, args);
208
+
209
+ this.stats.crossContractCalls++;
210
+
211
+ // Emit event
212
+ this.emit('crossContractCall', {
213
+ from: fromContract,
214
+ to: toContract,
215
+ function: functionName,
216
+ success: result.success,
217
+ blockNumber: this.blockchain?.getHeight?.() || 0
218
+ });
219
+
220
+ return result;
221
+ }
222
+
223
+ /**
224
+ * Process a transaction
225
+ *
226
+ * This is called by the blockchain when a new transaction arrives
227
+ */
228
+ async processTransaction(tx) {
229
+ // Validate transaction
230
+ if (!tx.to && !tx.data) {
231
+ throw new Error('Invalid transaction: no target or data');
232
+ }
233
+
234
+ // Contract deployment (no 'to' address)
235
+ if (!tx.to && tx.data) {
236
+ // Detect language from data or metadata
237
+ const language = tx.language || this._detectLanguage(tx.data);
238
+ return this.deployContract(tx.data, language, {
239
+ from: tx.from,
240
+ value: tx.value
241
+ });
242
+ }
243
+
244
+ // Contract call
245
+ if (tx.to && tx.data) {
246
+ const { functionName, args } = this._decodeCalldata(tx.data);
247
+ return this.executeCall(tx.to, functionName, args, {
248
+ from: tx.from,
249
+ value: tx.value
250
+ });
251
+ }
252
+
253
+ // Simple transfer (no data)
254
+ return this._processTransfer(tx);
255
+ }
256
+
257
+ /**
258
+ * Get contract information
259
+ */
260
+ getContract(address) {
261
+ return this.contracts.get(address) || null;
262
+ }
263
+
264
+ /**
265
+ * Get all deployed contracts
266
+ */
267
+ getAllContracts() {
268
+ return Array.from(this.contracts.values());
269
+ }
270
+
271
+ /**
272
+ * Get transaction receipt
273
+ */
274
+ getReceipt(txHash) {
275
+ return this.receipts.get(txHash) || null;
276
+ }
277
+
278
+ /**
279
+ * Get VM stats
280
+ */
281
+ getStats() {
282
+ const vmStats = this.vm?.getStats?.() || {};
283
+ return {
284
+ ...this.stats,
285
+ ...vmStats,
286
+ vmAvailable: !!this.vm
287
+ };
288
+ }
289
+
290
+ /**
291
+ * Encode function call using JAELIS ABI
292
+ */
293
+ encodeCall(functionName, args, types) {
294
+ if (JaelisABI) {
295
+ return JaelisABI.encodeFunctionCall(functionName, args, types);
296
+ }
297
+ // Fallback encoding
298
+ return Buffer.from(JSON.stringify({ functionName, args }));
299
+ }
300
+
301
+ /**
302
+ * Decode function call
303
+ */
304
+ decodeCall(data) {
305
+ if (JaelisABI) {
306
+ return JaelisABI.decodeFunctionCall(data);
307
+ }
308
+ // Fallback decoding
309
+ try {
310
+ return JSON.parse(data.toString());
311
+ } catch {
312
+ return { functionName: 'unknown', args: [] };
313
+ }
314
+ }
315
+
316
+ // ═══════════════════════════════════════════════════════════════
317
+ // PRIVATE METHODS
318
+ // ═══════════════════════════════════════════════════════════════
319
+
320
+ _generateTxHash(to, functionName, args, from) {
321
+ const crypto = require('crypto');
322
+ return '0x' + crypto.createHash('sha256')
323
+ .update(JSON.stringify({ to, functionName, args, from, timestamp: Date.now() }))
324
+ .digest('hex');
325
+ }
326
+
327
+ _detectLanguage(data) {
328
+ const code = typeof data === 'string' ? data : data.toString();
329
+
330
+ // Detect by patterns
331
+ if (code.includes('contract ') && code.includes('function ')) return 'solidity';
332
+ if (code.includes('#[program]') || code.includes('pub mod ')) return 'rust';
333
+ if (code.includes('module ') && code.includes('public fun ')) return 'move';
334
+ if (code.includes('recv_internal') || code.includes('method_id')) return 'func';
335
+ if (code.includes('#[contract]') && code.includes('fn ')) return 'cairo';
336
+
337
+ return 'solidity'; // Default
338
+ }
339
+
340
+ _decodeCalldata(data) {
341
+ // If it's already JSON
342
+ if (typeof data === 'object' && data.functionName) {
343
+ return data;
344
+ }
345
+
346
+ // Try JAELIS ABI decode
347
+ if (JaelisABI && Buffer.isBuffer(data)) {
348
+ try {
349
+ return JaelisABI.decodeFunctionCall(data);
350
+ } catch {
351
+ // Fall through
352
+ }
353
+ }
354
+
355
+ // Try JSON
356
+ try {
357
+ return JSON.parse(data.toString());
358
+ } catch {
359
+ return { functionName: 'fallback', args: [] };
360
+ }
361
+ }
362
+
363
+ async _processTransfer(tx) {
364
+ // Simple value transfer (no contract execution)
365
+ const receipt = {
366
+ transactionHash: this._generateTxHash(tx.to, 'transfer', [tx.value], tx.from),
367
+ blockNumber: this.blockchain?.getHeight?.() || 0,
368
+ from: tx.from,
369
+ to: tx.to,
370
+ value: tx.value,
371
+ status: 1,
372
+ gasUsed: 0 // ZERO FEES!
373
+ };
374
+
375
+ this.receipts.set(receipt.transactionHash, receipt);
376
+ this.emit('transfer', receipt);
377
+
378
+ return receipt;
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Factory function to create VM executor
384
+ */
385
+ function createVMExecutor(blockchain, options = {}) {
386
+ return new VMExecutor(blockchain, options);
387
+ }
388
+
389
+ module.exports = {
390
+ VMExecutor,
391
+ createVMExecutor,
392
+
393
+ // Re-export VM components
394
+ UnifiedJaelisVM,
395
+ JaelisABI,
396
+ DynamicContractManager
397
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jaelis-node",
3
- "version": "1.1.0",
4
- "description": "Official JAELIS Blockchain Node - Run a full node, validator, or bootstrap node on the JAELIS network",
3
+ "version": "1.2.0",
4
+ "description": "Official JAELIS Blockchain Node - Run a full node, validator, or bootstrap node with Cross-Chain Settlement (30+ chains!)",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
7
7
  "jaelis-node": "./bin/jaelis-node.js"
@@ -35,7 +35,16 @@
35
35
  "mcp",
36
36
  "full-node",
37
37
  "bootstrap-node",
38
- "rpc-server"
38
+ "rpc-server",
39
+ "cross-chain",
40
+ "settlement",
41
+ "light-client",
42
+ "interoperability",
43
+ "universal-state",
44
+ "solana",
45
+ "arbitrum",
46
+ "polygon",
47
+ "optimism"
39
48
  ],
40
49
  "author": "JAELIS Foundation",
41
50
  "license": "MIT",