@tradelayerprotocol/tradelayer 1.9.1
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/.claude/settings.local.json +13 -0
- package/.claude/skills/tl-algo/SKILL.md +255 -0
- package/.gitattributes +2 -0
- package/.github/workflows/publish.yaml +26 -0
- package/4mm.js +163 -0
- package/LICENSE +21 -0
- package/NPMSwapRefactor.zip +0 -0
- package/README.md +217 -0
- package/address.sh +26 -0
- package/algoAPI.js +581 -0
- package/analyzepsbt.js +92 -0
- package/apiEx.js +99 -0
- package/bb_hyperscalper.js +290 -0
- package/bbo_demo.js +111 -0
- package/buyer.js +622 -0
- package/client.js +50 -0
- package/createTxTest.js +26 -0
- package/createWallet.js +75 -0
- package/daytrader.js +531 -0
- package/decodeTest.js +69 -0
- package/fundingManager.js +144 -0
- package/index.js +4 -0
- package/listener.js +27 -0
- package/litecoreTxBuilder.js +1128 -0
- package/mmEx.js +356 -0
- package/networks.js +51 -0
- package/orderbook.js +200 -0
- package/package.json +34 -0
- package/perTradeQueue.js +36 -0
- package/projectsTLNPMTLNPM/package-lock.json +162 -0
- package/projectsTLNPMTLNPM/package.json +5 -0
- package/quick.js +32 -0
- package/quickFut.js +37 -0
- package/quickSell.js +37 -0
- package/relayerClient.js +117 -0
- package/run4mm.js +80 -0
- package/run_bbo_tracker.js +241 -0
- package/seller.js +443 -0
- package/session.js +45 -0
- package/setup-lin-ltc.sh +139 -0
- package/setup-lin.sh +203 -0
- package/setup-win-ltc.bat +108 -0
- package/setup-win.bat +167 -0
- package/spam_screamer_futures.js +222 -0
- package/tradelayer.js/.gitattributes +2 -0
- package/tradelayer.js/README.md +2 -0
- package/tradelayer.js/oldTests/activationTest.js +6 -0
- package/tradelayer.js/oldTests/base58.test.js +23 -0
- package/tradelayer.js/oldTests/base64Decode.test.js +16 -0
- package/tradelayer.js/oldTests/blocksRefactor.js +140 -0
- package/tradelayer.js/oldTests/checkVestBalance.js +25 -0
- package/tradelayer.js/oldTests/consensusHashProto.js +151 -0
- package/tradelayer.js/oldTests/contractOrderbook.js +243 -0
- package/tradelayer.js/oldTests/createPayload.js +0 -0
- package/tradelayer.js/oldTests/createTestnetAddr.js +43 -0
- package/tradelayer.js/oldTests/decode.js +205 -0
- package/tradelayer.js/oldTests/decodeTest.js +50 -0
- package/tradelayer.js/oldTests/displayTallyMap.js +19 -0
- package/tradelayer.js/oldTests/encodeDecode.js +340 -0
- package/tradelayer.js/oldTests/expressTest.js +29 -0
- package/tradelayer.js/oldTests/extractBlocksVanilla.js +214 -0
- package/tradelayer.js/oldTests/extractBlocksVanillaa.js +179 -0
- package/tradelayer.js/oldTests/extractPubkeyTest.js +60 -0
- package/tradelayer.js/oldTests/fillInputCacheProto.js +111 -0
- package/tradelayer.js/oldTests/getRawTxTest.js +22 -0
- package/tradelayer.js/oldTests/indexTest.js +26 -0
- package/tradelayer.js/oldTests/initTokensTest.js +32 -0
- package/tradelayer.js/oldTests/interfaceChild.js +129 -0
- package/tradelayer.js/oldTests/listenerChild.js +112 -0
- package/tradelayer.js/oldTests/opdecode.js +26 -0
- package/tradelayer.js/oldTests/options.js +79 -0
- package/tradelayer.js/oldTests/optxtest.js +116 -0
- package/tradelayer.js/oldTests/optxtest1.js +64 -0
- package/tradelayer.js/oldTests/oracle.test.js +32 -0
- package/tradelayer.js/oldTests/orderbook.test.js +36 -0
- package/tradelayer.js/oldTests/parsing.js +93 -0
- package/tradelayer.js/oldTests/payload.js +13 -0
- package/tradelayer.js/oldTests/persistenceUnitTest.js +23 -0
- package/tradelayer.js/oldTests/property.test.js +53 -0
- package/tradelayer.js/oldTests/propertyLevel.js +75 -0
- package/tradelayer.js/oldTests/propertyTest.js +32 -0
- package/tradelayer.js/oldTests/queryAddressTest.js +17 -0
- package/tradelayer.js/oldTests/salter.js +14 -0
- package/tradelayer.js/oldTests/tally.js +81 -0
- package/tradelayer.js/oldTests/tally.test.js +48 -0
- package/tradelayer.js/oldTests/tally2.js +124 -0
- package/tradelayer.js/oldTests/tally3.js +142 -0
- package/tradelayer.js/oldTests/tallyDiag.js +38 -0
- package/tradelayer.js/oldTests/testGetRaw.js +40 -0
- package/tradelayer.js/oldTests/testHexConvert.js +47 -0
- package/tradelayer.js/oldTests/testNewEncoding.js +96 -0
- package/tradelayer.js/oldTests/testNewEncoding2.js +113 -0
- package/tradelayer.js/oldTests/testNewEncoding3 +112 -0
- package/tradelayer.js/oldTests/testNewEncoding3.js +168 -0
- package/tradelayer.js/oldTests/testOPReturn.js +102 -0
- package/tradelayer.js/oldTests/testPayload.js +23 -0
- package/tradelayer.js/oldTests/testRaw.js +50 -0
- package/tradelayer.js/oldTests/testSendTooMuch.js +20 -0
- package/tradelayer.js/oldTests/testTxBuild +28 -0
- package/tradelayer.js/oldTests/testTxBuild.js +42 -0
- package/tradelayer.js/oldTests/tokenOrderbook.js +243 -0
- package/tradelayer.js/oldTests/txUtilsA.js +515 -0
- package/tradelayer.js/oldTests/validityUnitTest.js +53 -0
- package/tradelayer.js/oldTests/vaults.js +72 -0
- package/tradelayer.js/oldTests/volumeIndex.js +117 -0
- package/tradelayer.js/oldTests/volumeIndex2.js +88 -0
- package/tradelayer.js/output_base64.txt +1 -0
- package/tradelayer.js/package-lock.json +9967 -0
- package/tradelayer.js/package.json +61 -0
- package/tradelayer.js/server/index.js +88 -0
- package/tradelayer.js/server/litecoind.exe +0 -0
- package/tradelayer.js/src/activation.js +303 -0
- package/tradelayer.js/src/adjuster.js +77 -0
- package/tradelayer.js/src/amm.js +400 -0
- package/tradelayer.js/src/base256.js +55 -0
- package/tradelayer.js/src/base94.js +79 -0
- package/tradelayer.js/src/channels.js +1163 -0
- package/tradelayer.js/src/clearing.js +3109 -0
- package/tradelayer.js/src/clearlist.js +364 -0
- package/tradelayer.js/src/client.js +295 -0
- package/tradelayer.js/src/consensus.js +613 -0
- package/tradelayer.js/src/contractRegistry.js +964 -0
- package/tradelayer.js/src/db.js +89 -0
- package/tradelayer.js/src/init.js +24 -0
- package/tradelayer.js/src/insurance.js +347 -0
- package/tradelayer.js/src/interface.js +218 -0
- package/tradelayer.js/src/interfaceExpress.js +178 -0
- package/tradelayer.js/src/iou.js +509 -0
- package/tradelayer.js/src/listener.js +226 -0
- package/tradelayer.js/src/logic.js +1702 -0
- package/tradelayer.js/src/main.js +927 -0
- package/tradelayer.js/src/marginMap.js +2165 -0
- package/tradelayer.js/src/options.js +126 -0
- package/tradelayer.js/src/oracle.js +394 -0
- package/tradelayer.js/src/orderbook.js +4123 -0
- package/tradelayer.js/src/persistence.js +554 -0
- package/tradelayer.js/src/property.js +411 -0
- package/tradelayer.js/src/reOrg.js +41 -0
- package/tradelayer.js/src/scaling.js +145 -0
- package/tradelayer.js/src/tally.js +1275 -0
- package/tradelayer.js/src/tradeHistoryManager.js +552 -0
- package/tradelayer.js/src/txDecoder.js +584 -0
- package/tradelayer.js/src/txEncoder.js +610 -0
- package/tradelayer.js/src/txIndex.js +502 -0
- package/tradelayer.js/src/txUtils.js +1392 -0
- package/tradelayer.js/src/types.js +429 -0
- package/tradelayer.js/src/validity.js +3077 -0
- package/tradelayer.js/src/vaults.js +430 -0
- package/tradelayer.js/src/vesting.js +491 -0
- package/tradelayer.js/src/volumeIndex.js +618 -0
- package/tradelayer.js/src/walletInterface.js +220 -0
- package/tradelayer.js/src/walletListener.js +665 -0
- package/tradelayer.js/tests/256decode.js +82 -0
- package/tradelayer.js/tests/UTXOracle.js +205 -0
- package/tradelayer.js/tests/base94test.js +23 -0
- package/tradelayer.js/tests/cancelTxTest.js +62 -0
- package/tradelayer.js/tests/contractInterfaceTest.js +48 -0
- package/tradelayer.js/tests/decimalTest.js +65 -0
- package/tradelayer.js/tests/decoderTest.js +100 -0
- package/tradelayer.js/tests/deltaCount.js +47 -0
- package/tradelayer.js/tests/deltaCount2.js +60 -0
- package/tradelayer.js/tests/interfaceTest.js +37 -0
- package/tradelayer.js/tests/mainTest.js +53 -0
- package/tradelayer.js/tests/makeActivationTest.js +24 -0
- package/tradelayer.js/tests/maxHeightTest.js +49 -0
- package/tradelayer.js/tests/reverseHash.js +72 -0
- package/tradelayer.js/tests/sensitiveConsoleOutput.txt +267 -0
- package/tradelayer.js/tests/tallyTest.js +40 -0
- package/tradelayer.js/tests/testBuybacks.js +46 -0
- package/tradelayer.js/tests/testCodeHash.js +49 -0
- package/tradelayer.js/tests/testConsensusHash.js +91 -0
- package/tradelayer.js/tests/testDecode.js +30 -0
- package/tradelayer.js/tests/testEncodingLengths.js +129 -0
- package/tradelayer.js/tests/testGetTx +32 -0
- package/tradelayer.js/tests/testGetTx.js +32 -0
- package/tradelayer.js/tests/testHexHash.js +32 -0
- package/tradelayer.js/tests/testIndexHash.js +35 -0
- package/tradelayer.js/tests/testInitContracts.js +38 -0
- package/tradelayer.js/tests/testMaxConsensus.js +12 -0
- package/tradelayer.js/tests/testMaxSynth.js +44 -0
- package/tradelayer.js/tests/testMint.js +21 -0
- package/tradelayer.js/tests/testNetwork.js +33 -0
- package/tradelayer.js/tests/testOrderbookLoad.js +62 -0
- package/tradelayer.js/tests/testRebates.js +32 -0
- package/tradelayer.js/tests/testRedeem.js +22 -0
- package/tradelayer.js/tests/testTokenTrade.js +39 -0
- package/tradelayer.js/tests/testTxBuild.js +42 -0
- package/tradelayer.js/tests/testUTXOTrade.js +27 -0
- package/tradelayer.js/tests/tokenTradeHistory.js +27 -0
- package/tradelayer.js/tests/tradeFutures.js +40 -0
- package/tradelayer.js/tests/tradeHistoryExample.js +35 -0
- package/tradelayer.js/tests/tradeHistoryLoad.js +15 -0
- package/tradelayer.js/tests/txScanTest.js +134 -0
- package/tradelayer.js/tests/validateTest.js +136 -0
- package/tradelayer.js/tests/vestingTest.js +37 -0
- package/tradelayer.js/utils/activateMainnet.js +59 -0
- package/tradelayer.js/utils/activateMainnetDoge.js +63 -0
- package/tradelayer.js/utils/autocompactdb.js +23 -0
- package/tradelayer.js/utils/base64toHex.js +32 -0
- package/tradelayer.js/utils/broadcastDoge.js +38 -0
- package/tradelayer.js/utils/calcRedeem.js +19 -0
- package/tradelayer.js/utils/checkNetwork.js +27 -0
- package/tradelayer.js/utils/createAddress.js +48 -0
- package/tradelayer.js/utils/createAttestation.js +133 -0
- package/tradelayer.js/utils/createContract.js +118 -0
- package/tradelayer.js/utils/createOracle.js +94 -0
- package/tradelayer.js/utils/createwallet.js +20 -0
- package/tradelayer.js/utils/crossFuturesTrades.js +57 -0
- package/tradelayer.js/utils/crossTokenTrades.js +62 -0
- package/tradelayer.js/utils/dumpPriv.js +29 -0
- package/tradelayer.js/utils/generateChannel.js +34 -0
- package/tradelayer.js/utils/getInfo.js +21 -0
- package/tradelayer.js/utils/hardWipe.js +20 -0
- package/tradelayer.js/utils/hexTo64.js +16 -0
- package/tradelayer.js/utils/importAddress.js +28 -0
- package/tradelayer.js/utils/importpriv.js +20 -0
- package/tradelayer.js/utils/issueOracleContract.js +67 -0
- package/tradelayer.js/utils/issueTokens.js +41 -0
- package/tradelayer.js/utils/listunspent.js +66 -0
- package/tradelayer.js/utils/litecoinClient.js +30 -0
- package/tradelayer.js/utils/loadwallet.js +20 -0
- package/tradelayer.js/utils/publishOracle.js +113 -0
- package/tradelayer.js/utils/sendActivation.js +21 -0
- package/tradelayer.js/utils/sendChannelContractTrade.js +34 -0
- package/tradelayer.js/utils/sendChannelTokenTrade.js +34 -0
- package/tradelayer.js/utils/sendCommit.js +24 -0
- package/tradelayer.js/utils/sendDoge.js +62 -0
- package/tradelayer.js/utils/sendDogeMain.js +67 -0
- package/tradelayer.js/utils/sendDogeTx.js +46 -0
- package/tradelayer.js/utils/sendLTC.js +63 -0
- package/tradelayer.js/utils/sendMainnet.js +62 -0
- package/tradelayer.js/utils/sendTransfer.js +19 -0
- package/tradelayer.js/utils/sendVestTest.js +88 -0
- package/tradelayer.js/utils/sendWithdrawal.js +26 -0
- package/tradelayer.js/utils/simpleStart.js +8 -0
- package/tradelayer.js/utils/startStop.js +27 -0
- package/tradelayer.js/utils/structuredTrades.js +136 -0
- package/tradelayer.js/utils/verifySignature.js +90 -0
- package/tradelayer.js/utils/verifyWitnessAndScriptPubkey.js +41 -0
- package/tradelayer.js/utils/walletCache.js +172 -0
- package/tradelayer.js/utils/walletContractInterface.js +48 -0
- package/tradelayer.js/utils/walletFetchTxs.js +66 -0
- package/tradelayer.js/utils/walletUtils.js +97 -0
- package/tradelayer.js/utils/wipeDB.js +55 -0
- package/tradelayer.js/utils/wipeDBNotTx.js +50 -0
- package/txEncoder.js +529 -0
- package/utility.js +28 -0
- package/verifymessage.js +38 -0
- package/ws-transport.js +311 -0
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
const db = require('./db.js');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const crypto = require('crypto');
|
|
5
|
+
const util = require('util');
|
|
6
|
+
const fsPromises = fs.promises;
|
|
7
|
+
const basePath = path.join(__dirname);
|
|
8
|
+
|
|
9
|
+
class ConsensusDatabase {
|
|
10
|
+
static consensusVector = [];
|
|
11
|
+
constructor() {
|
|
12
|
+
if (ConsensusDatabase.instance) {
|
|
13
|
+
return ConsensusDatabase.instance;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const flaggedIPs = []
|
|
17
|
+
ConsensusDatabase.instance = this;
|
|
18
|
+
this.loadFlaggedIPsFromDb(); // Load flagged IPs from the database on initialization
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Store the consensus hash for a given block height.
|
|
23
|
+
* @param {Number} blockHeight - The height of the block.
|
|
24
|
+
* @param {String} consensusHash - The consensus hash for the block.
|
|
25
|
+
*/
|
|
26
|
+
static async storeConsensusHash(blockHeight, consensusHash) {
|
|
27
|
+
const query = { _id: `block-${blockHeight}` }; // Use _id as a unique identifier
|
|
28
|
+
const update = { $set: { blockHeight, consensusHash } }; // Update or insert block and consensus hash
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const base = await db.getDatabase('consensus')
|
|
32
|
+
await base.updateAsync(query, update, { upsert: true }); // Upsert to insert if it doesn't exist
|
|
33
|
+
console.log(`Consensus hash for block ${blockHeight} stored.`);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
console.error('Error storing consensus hash:', err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Retrieve the consensus hash for a given block height.
|
|
41
|
+
* @param {Number} blockHeight - The height of the block.
|
|
42
|
+
* @returns {String|null} - The consensus hash or null if not found.
|
|
43
|
+
*/
|
|
44
|
+
static async getConsensusHash(blockHeight) {
|
|
45
|
+
const query = { _id: `block-${blockHeight}` }; // Use _id to find based on the block number
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const base = await db.getDatabase('consensus')
|
|
49
|
+
const result = await base.findOneAsync(query); // Find based on the block height (_id)
|
|
50
|
+
if (result) {
|
|
51
|
+
return result.consensusHash; // Return the consensus hash if found
|
|
52
|
+
} else {
|
|
53
|
+
console.warn(`No consensus hash found for block ${blockHeight}`);
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
console.error('Error retrieving consensus hash:', err);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static async checkIfTxProcessed(txId) {
|
|
63
|
+
//console.log('inside checkIfTxProcessed ' + txId);
|
|
64
|
+
const base = await db.getDatabase('consensus')
|
|
65
|
+
const result = await base.findOneAsync({ _id: txId });
|
|
66
|
+
//console.log(result);
|
|
67
|
+
return result && result.processed === true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static async getTxParams(txId) {
|
|
71
|
+
const base = await db.getDatabase('consensus')
|
|
72
|
+
const result = await base.findOneAsync({ _id: txId });
|
|
73
|
+
return result.value.processed === true ? result.value.params : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
static async markTxAsProcessed(txId, params) {
|
|
77
|
+
let value = { processed: true, params };
|
|
78
|
+
const base = await db.getDatabase('consensus')
|
|
79
|
+
await base.updateAsync(
|
|
80
|
+
{ _id: txId },
|
|
81
|
+
{ $set: value },
|
|
82
|
+
{ upsert: true }
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static async getTxParamsForAddress(address) {
|
|
87
|
+
const base = await db.getDatabase('consensus')
|
|
88
|
+
const results = await base.findAsync({ "value.processed": true, "value.params.address": address });
|
|
89
|
+
return results.map(result => result.value.params);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static async getTxParamsForBlock(blockHeight) {
|
|
93
|
+
const base = await db.getDatabase('consensus')
|
|
94
|
+
const results = await base.findAsync({ "value.processed": true, "value.params.block": blockHeight });
|
|
95
|
+
return results.map(result => result.value.params);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
static async getMaxProcessedBlock() {
|
|
99
|
+
const base = await db.getDatabase('consensus')
|
|
100
|
+
const result = await base.findOneAsync({ _id: 'MaxProcessedHeight' });
|
|
101
|
+
return result ? result.value : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
static async getHighestBlockHeight(callback) {
|
|
105
|
+
const base = await db.getDatabase('consensus')
|
|
106
|
+
const result = await base.aggregate([
|
|
107
|
+
{ $group: { _id: null, maxBlockHeight: { $max: "$value.params.blockHeight" } } }
|
|
108
|
+
], (err, result) => {
|
|
109
|
+
if (err) {
|
|
110
|
+
callback(err, null);
|
|
111
|
+
} else {
|
|
112
|
+
const maxBlockHeight = result.length > 0 ? result[0].maxBlockHeight : null;
|
|
113
|
+
callback(null, maxBlockHeight);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
static async compareBlockHeights() {
|
|
120
|
+
const maxProcessedBlock = await this.getMaxProcessedBlock();
|
|
121
|
+
const highestBlockHeight = await this.getHighestBlockHeight();
|
|
122
|
+
|
|
123
|
+
const higherBlockHeight = Math.max(maxProcessedBlock, highestBlockHeight);
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
maxProcessedBlock,
|
|
127
|
+
highestBlockHeight,
|
|
128
|
+
higherBlockHeight
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
// Function to generate SHA-256 hash
|
|
134
|
+
static generateHash(input) {
|
|
135
|
+
const hash = crypto.createHash('sha256');
|
|
136
|
+
hash.update(input);
|
|
137
|
+
return hash.digest('hex');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 1. txIndexHash: Hash the filtered txIndex
|
|
141
|
+
static async txIndexHash() {
|
|
142
|
+
try {
|
|
143
|
+
const base = await db.getDatabase('txIndex')
|
|
144
|
+
const txIndex = await base.findAsync({});
|
|
145
|
+
const filteredTxIndex = txIndex.filter(tx => tx._id.startsWith('tx'));
|
|
146
|
+
const filteredTxIndexString = JSON.stringify(filteredTxIndex);
|
|
147
|
+
const hash = this.generateHash(filteredTxIndexString);
|
|
148
|
+
console.log('txIndexHash:', hash);
|
|
149
|
+
return hash;
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error('Error generating txIndex hash:', err);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Function to get the latest instance of a DB
|
|
156
|
+
static async getLatestInstance(dbName) {
|
|
157
|
+
const base = await db.getDatabase(dbName)
|
|
158
|
+
const data = await base.findAsync({});
|
|
159
|
+
return data.length > 0 ? data[data.length - 1] : null; // Get the latest entry
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Function to get all instances from a DB
|
|
163
|
+
static async getAllInstances(dbName) {
|
|
164
|
+
const base = await db.getDatabase(dbName)
|
|
165
|
+
const data = await base.findAsync({});
|
|
166
|
+
return data; // Return all entries
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Function to generate stateConsensusHash based on various DBs
|
|
170
|
+
// Function to generate stateConsensusHash based on various DBs
|
|
171
|
+
static async stateConsensusHash(snapshot) {
|
|
172
|
+
try {
|
|
173
|
+
// Retrieve latest instance from tally.db and activations.db
|
|
174
|
+
const latestTally = await this.getLatestInstance('tallyMap');
|
|
175
|
+
const latestActivation = await this.getLatestInstance('activations');
|
|
176
|
+
|
|
177
|
+
// Retrieve everything from other specified DBs
|
|
178
|
+
const channels = await this.getAllInstances('channels');
|
|
179
|
+
const clearlists = await this.getAllInstances('clearlists');
|
|
180
|
+
const contractList = await this.getAllInstances('contractList');
|
|
181
|
+
const feeCache = await this.getAllInstances('feeCache');
|
|
182
|
+
const insurance = await this.getAllInstances('insurance');
|
|
183
|
+
const marginMaps = await this.getAllInstances('marginMaps');
|
|
184
|
+
const oracleData = await this.getAllInstances('oracleData');
|
|
185
|
+
const oracleList = await this.getAllInstances('oracleList');
|
|
186
|
+
const orderBooks = await this.getAllInstances('orderBooks');
|
|
187
|
+
const propertyList = await this.getAllInstances('propertyList');
|
|
188
|
+
const syntheticTokens = await this.getAllInstances('syntheticTokens');
|
|
189
|
+
const vaults = await this.getAllInstances('vaults');
|
|
190
|
+
const volumeIndex = await this.getAllInstances('volumeIndex');
|
|
191
|
+
const withdrawQueue = await this.getAllInstances('withdrawQueue');
|
|
192
|
+
|
|
193
|
+
// Combine all the retrieved data into a single structure
|
|
194
|
+
const combinedState = {
|
|
195
|
+
latestTally,
|
|
196
|
+
latestActivation,
|
|
197
|
+
channels,
|
|
198
|
+
clearlists,
|
|
199
|
+
contractList,
|
|
200
|
+
feeCache,
|
|
201
|
+
insurance,
|
|
202
|
+
marginMaps,
|
|
203
|
+
oracleData,
|
|
204
|
+
oracleList,
|
|
205
|
+
orderBooks,
|
|
206
|
+
propertyList,
|
|
207
|
+
syntheticTokens,
|
|
208
|
+
vaults,
|
|
209
|
+
volumeIndex,
|
|
210
|
+
withdrawQueue
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Convert combined data to string
|
|
214
|
+
const combinedStateString = JSON.stringify(combinedState);
|
|
215
|
+
|
|
216
|
+
// Generate and return the SHA-256 hash of the combined state
|
|
217
|
+
const hash = this.generateHash(combinedStateString);
|
|
218
|
+
console.log('stateConsensusHash:', hash);
|
|
219
|
+
if(!snapshot){
|
|
220
|
+
return hash;
|
|
221
|
+
}else if(snapshot){
|
|
222
|
+
return {hash: hash, state: combinedStateString}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
} catch (err) {
|
|
226
|
+
console.error('Error generating stateConsensus hash:', err);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Function to hash files in the specified folder
|
|
231
|
+
static async hashFiles() {
|
|
232
|
+
try {
|
|
233
|
+
let combinedContent = ''; // Initialize empty string to hold combined file content
|
|
234
|
+
|
|
235
|
+
const jsFiles = [
|
|
236
|
+
'activation', 'amm', 'channels', 'clearing', 'clearlist', 'consensus', 'contractRegistry',
|
|
237
|
+
'insurance', 'logic', 'main', 'marginMap', 'options', 'oracle', 'orderbook',
|
|
238
|
+
'persistence', 'property', 'reOrg', 'tally', 'txDecoder', 'txIndex', 'types',
|
|
239
|
+
'validity', 'vaults', 'vesting', 'volumeIndex'
|
|
240
|
+
];
|
|
241
|
+
// Loop through each file, read its content, and append to combinedContent
|
|
242
|
+
for (const file of jsFiles) {
|
|
243
|
+
console.log('file name '+file)
|
|
244
|
+
const name = file+'.js'
|
|
245
|
+
const filePath = path.join(basePath, name);
|
|
246
|
+
|
|
247
|
+
if (fs.existsSync(filePath)) {
|
|
248
|
+
const fileContent = await fsPromises.readFile(filePath, 'utf8');
|
|
249
|
+
combinedContent += fileContent; // Append file content
|
|
250
|
+
} else {
|
|
251
|
+
console.warn(`File not found: ${filePath}`); // Warn if the file is missing
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Stringify the combined content
|
|
256
|
+
const combinedContentString = JSON.stringify(combinedContent);
|
|
257
|
+
//console.log('combinedContent '+combinedContentString)
|
|
258
|
+
|
|
259
|
+
// Generate a SHA-256 hash of the combined content
|
|
260
|
+
const hash = crypto.createHash('sha256');
|
|
261
|
+
hash.update(combinedContentString);
|
|
262
|
+
const finalHash = hash.digest('hex');
|
|
263
|
+
|
|
264
|
+
console.log('Final SHA-256 Hash:', finalHash);
|
|
265
|
+
return finalHash;
|
|
266
|
+
} catch (err) {
|
|
267
|
+
console.error('Error reading or hashing files:', err);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Function to fetch the latest activation from activations.db and push into the consensus vector
|
|
272
|
+
static async pushLatestActivationToConsensusVector() {
|
|
273
|
+
try {
|
|
274
|
+
const activationsDb = await db.getDatabase('activations');
|
|
275
|
+
const activations = await activationsDb.findAsync({ _id: 'activationsList' });
|
|
276
|
+
|
|
277
|
+
if (!activations || !activations[0] || !activations[0].value) {
|
|
278
|
+
console.log('No activations found in the database.');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const activationsList = JSON.parse(activations[0].value);
|
|
283
|
+
let latestActivation = null;
|
|
284
|
+
let maxBlock = -1;
|
|
285
|
+
|
|
286
|
+
for (const key in activationsList) {
|
|
287
|
+
const activation = activationsList[key];
|
|
288
|
+
if (activation.activationBlock && activation.activationBlock > maxBlock) {
|
|
289
|
+
maxBlock = activation.activationBlock;
|
|
290
|
+
latestActivation = activation;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (!latestActivation) {
|
|
295
|
+
console.log('No valid activation with an activationBlock found.');
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const projectPath = path.resolve(__dirname);
|
|
300
|
+
const codeHash = await ConsensusDatabase.hashFiles(projectPath) || '';
|
|
301
|
+
const wasmCodeHash = '';
|
|
302
|
+
const consensusHash = await ConsensusDatabase.stateConsensusHash();
|
|
303
|
+
|
|
304
|
+
const newConsensusEntry = {
|
|
305
|
+
activation: latestActivation,
|
|
306
|
+
codeHash,
|
|
307
|
+
wasmCodeHash,
|
|
308
|
+
consensusHash,
|
|
309
|
+
blockNumber: maxBlock,
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
this.consensusVector.push(newConsensusEntry);
|
|
313
|
+
console.log('Latest activation pushed to consensus vector:', newConsensusEntry);
|
|
314
|
+
return newConsensusEntry;
|
|
315
|
+
|
|
316
|
+
} catch (err) {
|
|
317
|
+
console.error('Error fetching latest activation or updating consensus vector:', err);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
// Function to save the consensus vector to the consensus.db file
|
|
324
|
+
static async saveConsensusVector() {
|
|
325
|
+
try {
|
|
326
|
+
const consensusDb = await db.getDatabase('consensus');
|
|
327
|
+
|
|
328
|
+
// Check if a document with _id "consensusVector" exists
|
|
329
|
+
const existingConsensusVector = await consensusDb.findOneAsync({ _id: 'consensusVector' });
|
|
330
|
+
|
|
331
|
+
if (existingConsensusVector) {
|
|
332
|
+
// If it exists, update the document
|
|
333
|
+
await consensusDb.updateAsync(
|
|
334
|
+
{ _id: 'consensusVector' },
|
|
335
|
+
{ $set: { vector: consensusVector } },
|
|
336
|
+
{ upsert: true }
|
|
337
|
+
);
|
|
338
|
+
console.log('Consensus vector updated in consensus.db');
|
|
339
|
+
} else {
|
|
340
|
+
// If it doesn't exist, insert a new document
|
|
341
|
+
await consensusDb.insertAsync({
|
|
342
|
+
_id: 'consensusVector',
|
|
343
|
+
vector: consensusVector
|
|
344
|
+
});
|
|
345
|
+
console.log('Consensus vector saved to consensus.db');
|
|
346
|
+
}
|
|
347
|
+
} catch (err) {
|
|
348
|
+
console.error('Error saving consensus vector to consensus.db:', err);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
static async loadConsensusVector() {
|
|
353
|
+
try {
|
|
354
|
+
const consensusDb = await db.getDatabase('consensus');
|
|
355
|
+
|
|
356
|
+
// Check if a document with _id "consensusVector" exists
|
|
357
|
+
const existingConsensusVector = await consensusDb.findOneAsync({ _id: 'consensusVector' });
|
|
358
|
+
|
|
359
|
+
if (existingConsensusVector) {
|
|
360
|
+
return existingConsensusVector
|
|
361
|
+
} else {
|
|
362
|
+
return console.log('No Consensus vector found.');
|
|
363
|
+
}
|
|
364
|
+
} catch (err) {
|
|
365
|
+
console.error('Error saving consensus vector to consensus.db:', err);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
static async generateHashes() {
|
|
370
|
+
// These are updated to match the actual method names
|
|
371
|
+
this.txIndexHash = await this.txIndexHash(); // For transaction index hash
|
|
372
|
+
this.consensusStateHash = await this.stateConsensusHash(); // For consensus state hash
|
|
373
|
+
this.codeHash = await this.hashFiles(path.resolve(__dirname)); // For code hash
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Consensus handshake function: compares local and incoming hashes
|
|
377
|
+
static async consensusHandshake(incomingHashes) {
|
|
378
|
+
await this.generateHashes(); // Generate both JS and WASM hashes
|
|
379
|
+
await this.populateConsensusVectorFromActivations();
|
|
380
|
+
const localHashes = {
|
|
381
|
+
txIndexHash: this.txIndexHash,
|
|
382
|
+
consensusStateHash: this.consensusStateHash,
|
|
383
|
+
codeHash: this.codeHash || '', // JavaScript hash
|
|
384
|
+
wasmCodeHash: this.wasmCodeHash || '' // WASM/Rust hash
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
console.log('Local Hashes:', localHashes);
|
|
388
|
+
console.log('Incoming Hashes:', incomingHashes);
|
|
389
|
+
|
|
390
|
+
const txIndexMatch = localHashes.txIndexHash === incomingHashes.txIndexHash;
|
|
391
|
+
const consensusStateMatch = localHashes.consensusStateHash === incomingHashes.consensusStateHash;
|
|
392
|
+
const codeHashMatch = localHashes.codeHash === incomingHashes.codeHash;
|
|
393
|
+
const wasmCodeHashMatch = localHashes.wasmCodeHash === incomingHashes.wasmCodeHash;
|
|
394
|
+
|
|
395
|
+
if (!txIndexMatch) {
|
|
396
|
+
console.warn('Transaction index hash does not match!');
|
|
397
|
+
}
|
|
398
|
+
if (!consensusStateMatch) {
|
|
399
|
+
console.warn('Consensus state hash does not match!');
|
|
400
|
+
}
|
|
401
|
+
if (!codeHashMatch) {
|
|
402
|
+
console.warn('Code hash does not match!');
|
|
403
|
+
}
|
|
404
|
+
if (!wasmCodeHashMatch) {
|
|
405
|
+
console.warn('WASM code hash does not match!');
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const match = txIndexMatch && consensusStateMatch && codeHashMatch && wasmCodeHashMatch;
|
|
409
|
+
|
|
410
|
+
return match;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
async investigateDiscrepancy(incomingHashes) {
|
|
415
|
+
try {
|
|
416
|
+
// Load the latest activations list
|
|
417
|
+
const activations = await this.loadActivationsList();
|
|
418
|
+
|
|
419
|
+
// Loop through the activations to compare with incoming codeHash
|
|
420
|
+
for (const [key, activation] of Object.entries(activations)) {
|
|
421
|
+
if (activation.codeHash === incomingHashes.codeHash) {
|
|
422
|
+
// If a match is found, check if the consensus hash also matches
|
|
423
|
+
if (activation.consensusHash === incomingHashes.consensusHash) {
|
|
424
|
+
return { status: 'match', message: 'Code and consensus hash match the existing version.' };
|
|
425
|
+
} else {
|
|
426
|
+
return { status: 'partial-match', message: 'Code hash matches but consensus hash differs.' };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// If no matches are found
|
|
432
|
+
return { status: 'unknown', message: 'No matching code hash found in the activations list.' };
|
|
433
|
+
|
|
434
|
+
} catch (error) {
|
|
435
|
+
console.error('Error investigating discrepancy:', error);
|
|
436
|
+
return { status: 'error', message: 'Error investigating discrepancy.' };
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Function to call the handshake and handle discrepancies
|
|
441
|
+
// Function to call the handshake and handle discrepancies
|
|
442
|
+
// Function to call the handshake and handle discrepancies
|
|
443
|
+
static async verifyConsensus(incomingHashes) {
|
|
444
|
+
const isHandshakeSuccessful = await this.consensusHandshake(incomingHashes);
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
if (isHandshakeSuccessful) {
|
|
448
|
+
console.log("Handshake successful, consensus verified.");
|
|
449
|
+
return true;
|
|
450
|
+
} else {
|
|
451
|
+
console.log("Handshake failed, investigating discrepancies...");
|
|
452
|
+
const status = await this.investigateDiscrepancy(incomingHashes);
|
|
453
|
+
|
|
454
|
+
if (status.status === 'unknown') {
|
|
455
|
+
// No match found for the codeHash - claim is suspicious
|
|
456
|
+
console.log("No matching codeHash found. This could be BS or a false claim.");
|
|
457
|
+
return false; // Call BS here and return false
|
|
458
|
+
} else if (status.status === 'partial-match') {
|
|
459
|
+
// CodeHash matches, but consensusHash differs
|
|
460
|
+
console.log("CodeHash matches but consensusHash differs. Attempting to reconstruct consensus...");
|
|
461
|
+
|
|
462
|
+
// Call a function to reconstruct consensus based on the incoming codeHash
|
|
463
|
+
const reconstructedConsensus = await this.reconstructConsensus(incomingHashes.codeHash);
|
|
464
|
+
|
|
465
|
+
// Compare the reconstructed consensus with the incoming consensusHash
|
|
466
|
+
if (reconstructedConsensus === incomingHashes.consensusHash) {
|
|
467
|
+
console.log("Consensus reconstructed successfully, matches the incoming hash.");
|
|
468
|
+
return true;
|
|
469
|
+
} else {
|
|
470
|
+
console.log("Reconstructed consensus does not match the incoming hash. Consensus mismatch.");
|
|
471
|
+
return false; // Return false if consensus reconstruction fails
|
|
472
|
+
}
|
|
473
|
+
} else if (status.status === 'match') {
|
|
474
|
+
// Everything matches, but somehow the handshake failed earlier, let's proceed anyway
|
|
475
|
+
console.log("Code and consensus hash match, but handshake failed earlier. Proceeding...");
|
|
476
|
+
return true;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return false; // Default to false if nothing else matches
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
// Function to reconstruct consensus based on codeHash
|
|
485
|
+
static async reconstructConsensus(codeHash) {
|
|
486
|
+
try {
|
|
487
|
+
// Load the activations list to ensure we have the latest consensus state
|
|
488
|
+
const activations = await this.loadActivationsList();
|
|
489
|
+
|
|
490
|
+
// Find the matching activation by codeHash
|
|
491
|
+
for (const [key, activation] of Object.entries(activations)) {
|
|
492
|
+
if (activation.codeHash === codeHash) {
|
|
493
|
+
console.log('Found matching activation for reconstruction:', activation);
|
|
494
|
+
|
|
495
|
+
// Regenerate the consensus state based on the activation we found
|
|
496
|
+
const reconstructedConsensus = await this.stateConsensusHash();
|
|
497
|
+
|
|
498
|
+
// Log and return the reconstructed consensus hash
|
|
499
|
+
console.log('Reconstructed consensus hash:', reconstructedConsensus);
|
|
500
|
+
return reconstructedConsensus;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// If no matching activation is found, return null
|
|
505
|
+
return null;
|
|
506
|
+
|
|
507
|
+
} catch (error) {
|
|
508
|
+
console.error('Error during consensus reconstruction:', error);
|
|
509
|
+
return null; // Return null in case of an error
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
static async crossReferenceFlagList(incomingFlagList) {
|
|
514
|
+
for (const flaggedNode of incomingFlagList) {
|
|
515
|
+
const localEntry = flaggedIPs.find(entry => entry.ip === flaggedNode.ip);
|
|
516
|
+
|
|
517
|
+
if (localEntry) {
|
|
518
|
+
localEntry.flagCount += flaggedNode.flagCount;
|
|
519
|
+
localEntry.reason += `; ${flaggedNode.reason}`;
|
|
520
|
+
localEntry.timestamp = new Date().toISOString();
|
|
521
|
+
} else {
|
|
522
|
+
flaggedIPs.push(flaggedNode);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
static async flagIP(ipAddress, reason) {
|
|
528
|
+
const existingEntry = flaggedIPs.find(entry => entry.ip === ipAddress);
|
|
529
|
+
if (existingEntry) {
|
|
530
|
+
existingEntry.flagCount += 1;
|
|
531
|
+
existingEntry.timestamp = new Date().toISOString();
|
|
532
|
+
} else {
|
|
533
|
+
flaggedIPs.push({
|
|
534
|
+
ip: ipAddress,
|
|
535
|
+
flagCount: 1,
|
|
536
|
+
reason: reason,
|
|
537
|
+
timestamp: new Date().toISOString()
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
console.log(`IP ${ipAddress} flagged for reason: ${reason}`);
|
|
541
|
+
// Save the updated flagged IP list to the database
|
|
542
|
+
await this.saveFlaggedIPsToDb();
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// Function to populate consensus vector using the activations blob
|
|
546
|
+
static async populateConsensusVectorFromActivations() {
|
|
547
|
+
try {
|
|
548
|
+
const activations = await this.loadActivationsList();
|
|
549
|
+
|
|
550
|
+
for (const [key, activation] of Object.entries(activations)) {
|
|
551
|
+
if (activation.active) {
|
|
552
|
+
const newEntry = {
|
|
553
|
+
codeHash: activation.codeHash || '', // The code hash for this activation
|
|
554
|
+
activationBlock: activation.activationBlock || -1, // The block it was activated
|
|
555
|
+
consensusHash: activation.consensusHash || null // Optional, if available
|
|
556
|
+
};
|
|
557
|
+
|
|
558
|
+
this.consensusVector.push(newEntry);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
console.log('Consensus vector populated from activations:', this.consensusVector);
|
|
563
|
+
return this.consensusVector;
|
|
564
|
+
|
|
565
|
+
} catch (err) {
|
|
566
|
+
console.error('Error populating consensus vector from activations:', err);
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// Save the flagged IPs list to the database
|
|
572
|
+
static async saveFlaggedIPsToDb() {
|
|
573
|
+
try {
|
|
574
|
+
const flaggedIPsDb = db.getDatabase('flaggedIPs');
|
|
575
|
+
await flaggedIPsDb.updateAsync(
|
|
576
|
+
{ _id: 'flaggedIPsList' },
|
|
577
|
+
{ $set: { value: JSON.stringify(this.flaggedIPs) } },
|
|
578
|
+
{ upsert: true } // Insert if not found
|
|
579
|
+
);
|
|
580
|
+
console.log('Flagged IP list saved to the database.');
|
|
581
|
+
} catch (error) {
|
|
582
|
+
console.error('Error saving flagged IP list to the database:', error);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Load the flagged IPs list from the database
|
|
587
|
+
static async loadFlaggedIPsFromDb() {
|
|
588
|
+
try {
|
|
589
|
+
const flaggedIPsDb = await db.getDatabase('flaggedIPs');
|
|
590
|
+
const entry = await flaggedIPsDb.findOneAsync({ _id: 'flaggedIPsList' });
|
|
591
|
+
|
|
592
|
+
if (entry && entry.value) {
|
|
593
|
+
this.flaggedIPs = JSON.parse(entry.value);
|
|
594
|
+
console.log('Flagged IP list loaded from the database.');
|
|
595
|
+
} else {
|
|
596
|
+
this.flaggedIPs = []; // Initialize to an empty list if not found in DB
|
|
597
|
+
console.log('No flagged IP list found in the database. Initialized with empty list.');
|
|
598
|
+
}
|
|
599
|
+
} catch (error) {
|
|
600
|
+
console.error('Error loading flagged IP list from the database:', error);
|
|
601
|
+
this.flaggedIPs = []; // Initialize to an empty list on error
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// Method to get the current flagged IPs list
|
|
606
|
+
static getFlaggedIPs() {
|
|
607
|
+
return this.flaggedIPs;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
module.exports = ConsensusDatabase;
|
|
613
|
+
|