trac-msb 0.2.6 → 0.2.8
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/.github/workflows/publish.yml +9 -16
- package/docs/networking-dualstack-plan.md +75 -0
- package/docs/networking-layer-redesign.md +155 -0
- package/msb.mjs +11 -23
- package/package.json +2 -3
- package/rpc/{create_server.mjs → create_server.js} +2 -2
- package/rpc/{handlers.mjs → handlers.js} +5 -5
- package/rpc/routes/{index.mjs → index.js} +1 -1
- package/rpc/routes/{v1.mjs → v1.js} +1 -1
- package/rpc/{rpc_server.mjs → rpc_server.js} +1 -1
- package/rpc/rpc_services.js +4 -4
- package/src/config/config.js +137 -0
- package/src/config/env.js +61 -0
- package/src/core/network/Network.js +131 -72
- package/src/core/network/identity/NetworkWalletFactory.js +3 -4
- package/src/core/network/messaging/NetworkMessages.js +12 -11
- package/src/core/network/messaging/handlers/GetRequestHandler.js +5 -4
- package/src/core/network/messaging/handlers/ResponseHandler.js +4 -5
- package/src/core/network/messaging/handlers/RoleOperationHandler.js +17 -19
- package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +44 -38
- package/src/core/network/messaging/handlers/TransferOperationHandler.js +29 -25
- package/src/core/network/messaging/handlers/base/BaseOperationHandler.js +20 -21
- package/src/core/network/messaging/routes/NetworkMessageRouter.js +24 -20
- package/src/core/network/messaging/validators/AdminResponse.js +2 -2
- package/src/core/network/messaging/validators/CustomNodeResponse.js +2 -2
- package/src/core/network/messaging/validators/PartialBootstrapDeployment.js +3 -3
- package/src/core/network/messaging/validators/PartialRoleAccess.js +15 -12
- package/src/core/network/messaging/validators/PartialTransaction.js +9 -10
- package/src/core/network/messaging/validators/PartialTransfer.js +10 -7
- package/src/core/network/messaging/validators/ValidatorResponse.js +2 -2
- package/src/core/network/messaging/validators/base/BaseResponse.js +13 -5
- package/src/core/network/messaging/validators/base/PartialOperation.js +37 -21
- package/src/core/network/services/ConnectionManager.js +248 -62
- package/src/core/network/services/MessageOrchestrator.js +83 -0
- package/src/core/network/services/TransactionPoolService.js +9 -8
- package/src/core/network/services/ValidatorObserverService.js +95 -34
- package/src/core/state/State.js +136 -139
- package/src/core/state/utils/address.js +18 -16
- package/src/core/state/utils/adminEntry.js +17 -16
- package/src/core/state/utils/deploymentEntry.js +15 -15
- package/src/core/state/utils/transaction.js +3 -95
- package/src/index.js +153 -201
- package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +36 -32
- package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +39 -42
- package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +20 -20
- package/src/messages/partialStateMessages/PartialStateMessageOperations.js +29 -22
- package/src/utils/check.js +21 -17
- package/src/utils/cliCommands.js +11 -11
- package/src/utils/constants.js +2 -9
- package/src/utils/fileUtils.js +1 -4
- package/src/utils/helpers.js +9 -20
- package/src/utils/migrationUtils.js +2 -2
- package/src/utils/normalizers.js +10 -9
- package/tests/acceptance/v1/account/account.test.mjs +2 -2
- package/tests/acceptance/v1/balance/balance.test.mjs +1 -1
- package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +11 -2
- package/tests/acceptance/v1/rpc.test.mjs +9 -9
- package/tests/acceptance/v1/tx/tx.test.mjs +4 -2
- package/tests/acceptance/v1/tx-details/tx-details.test.mjs +7 -3
- package/tests/fixtures/check.fixtures.js +42 -42
- package/tests/fixtures/protobuf.fixtures.js +27 -26
- package/tests/helpers/StateNetworkFactory.js +3 -5
- package/tests/helpers/autobaseTestHelpers.js +48 -2
- package/tests/helpers/config.js +3 -0
- package/tests/helpers/setupApplyTests.js +89 -82
- package/tests/helpers/transactionPayloads.mjs +26 -12
- package/tests/integration/apply/addAdmin/addAdminBasic.test.js +10 -9
- package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +20 -19
- package/tests/integration/apply/addIndexer.test.js +23 -21
- package/tests/integration/apply/addWhitelist.test.js +9 -9
- package/tests/integration/apply/addWriter.test.js +33 -32
- package/tests/integration/apply/banValidator.test.js +16 -9
- package/tests/integration/apply/postTx/invalidSubValues.test.js +4 -4
- package/tests/integration/apply/postTx/postTx.test.js +7 -33
- package/tests/integration/apply/removeIndexer.test.js +11 -7
- package/tests/integration/apply/removeWriter.test.js +20 -19
- package/tests/integration/apply/transfer.test.js +18 -16
- package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +2 -2
- package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +2 -1
- package/tests/unit/messageOperations/assembleAdminMessage.test.js +9 -10
- package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +3 -2
- package/tests/unit/messageOperations/assemblePostTransaction.test.js +25 -43
- package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +2 -2
- package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +2 -2
- package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +5 -4
- package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +4 -3
- package/tests/unit/network/ConnectionManager.test.js +41 -70
- package/tests/unit/network/NetworkWalletFactory.test.js +14 -14
- package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +6 -6
- package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +8 -8
- package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +6 -5
- package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +24 -23
- package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +10 -16
- package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +2 -1
- package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +45 -41
- package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +3 -7
- package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +17 -16
- package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +3 -4
- package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +2 -1
- package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +2 -1
- package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +23 -25
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +2 -1
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +19 -18
- package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +5 -4
- package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +4 -3
- package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +2 -1
- package/tests/unit/state/apply/common/commonScenarioHelper.js +3 -4
- package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +2 -2
- package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +2 -2
- package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +2 -1
- package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +2 -1
- package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +2 -1
- package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +2 -1
- package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +11 -10
- package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +6 -5
- package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +6 -7
- package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +35 -34
- package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +44 -43
- package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +26 -25
- package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +2 -1
- package/tests/unit/state/stateModule.test.js +0 -1
- package/tests/unit/state/stateTestUtils.js +7 -3
- package/tests/unit/state/utils/address.test.js +3 -3
- package/tests/unit/state/utils/adminEntry.test.js +10 -9
- package/tests/unit/utils/check/adminControlOperation.test.js +3 -3
- package/tests/unit/utils/check/balanceInitializationOperation.test.js +2 -2
- package/tests/unit/utils/check/bootstrapDeploymentOperation.test.js +2 -3
- package/tests/unit/utils/check/common.test.js +7 -6
- package/tests/unit/utils/check/coreAdminOperation.test.js +3 -3
- package/tests/unit/utils/check/roleAccessOperation.test.js +3 -2
- package/tests/unit/utils/check/transactionOperation.test.js +3 -3
- package/tests/unit/utils/check/transferOperation.test.js +3 -3
- package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +2 -1
- package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +2 -1
- package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +7 -0
- package/tests/unit/utils/utils.test.js +0 -1
- package/src/core/state/utils/indexerEntry.js +0 -105
- package/src/utils/crypto.js +0 -11
- package/tests/unit/state/utils/indexerEntry.test.js +0 -83
- package/tests/unit/state/utils/transaction.test.js +0 -97
- package/tests/unit/utils/crypto/createHash.test.js +0 -15
- /package/rpc/{constants.mjs → constants.js} +0 -0
- /package/rpc/{cors.mjs → cors.js} +0 -0
- /package/rpc/utils/{confirmedParameter.mjs → confirmedParameter.js} +0 -0
- /package/rpc/utils/{helpers.mjs → helpers.js} +0 -0
- /package/rpc/utils/{url.mjs → url.js} +0 -0
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
ACK_INTERVAL
|
|
25
25
|
} from '../../src/utils/constants.js';
|
|
26
26
|
import { testKeyPair1 } from '../fixtures/apply.fixtures.js';
|
|
27
|
+
import { createConfig, ENV } from '../../src/config/env.js';
|
|
27
28
|
|
|
28
29
|
export class StateNetworkFactory {
|
|
29
30
|
|
|
@@ -106,11 +107,8 @@ export class StateNetworkFactory {
|
|
|
106
107
|
for (let i = 0; i < nodes; i++) {
|
|
107
108
|
const mnemonic = i === 0 ? testKeyPair1.mnemonic : null;
|
|
108
109
|
const wallet = await createWallet(mnemonic);
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
enable_error_apply_logs: true,
|
|
112
|
-
...stateOptions
|
|
113
|
-
});
|
|
110
|
+
const stateConfig = createConfig(ENV.DEVELOPMENT, { ...stateOptions, bootstrap: bootstrapKey })
|
|
111
|
+
const state = new State(stateStores[i].session(), wallet, stateConfig);
|
|
114
112
|
|
|
115
113
|
bases[i]._handlers.apply = state.applyHandler;
|
|
116
114
|
descriptors.push({
|
|
@@ -8,7 +8,7 @@ import Autobase from 'autobase';
|
|
|
8
8
|
import Hyperbee from 'hyperbee';
|
|
9
9
|
import b4a from 'b4a';
|
|
10
10
|
import PeerWallet from 'trac-wallet';
|
|
11
|
-
import
|
|
11
|
+
import Hypercore from 'hypercore';
|
|
12
12
|
import {
|
|
13
13
|
ACK_INTERVAL,
|
|
14
14
|
AUTOBASE_VALUE_ENCODING,
|
|
@@ -16,9 +16,55 @@ import {
|
|
|
16
16
|
HYPERBEE_VALUE_ENCODING,
|
|
17
17
|
TRAC_NAMESPACE
|
|
18
18
|
} from '../../src/utils/constants.js';
|
|
19
|
+
import Writer from 'autobase/lib/writer.js';
|
|
19
20
|
|
|
20
21
|
const argv = typeof globalThis.Bare !== 'undefined' ? globalThis.Bare.argv : process.argv;
|
|
21
22
|
|
|
23
|
+
|
|
24
|
+
const originalWriterOpen = Writer.prototype._open;
|
|
25
|
+
Writer.prototype._open = async function patchedWriterOpen(...args) {
|
|
26
|
+
try {
|
|
27
|
+
return await originalWriterOpen.apply(this, args);
|
|
28
|
+
} catch (err) {
|
|
29
|
+
// On teardown GH runners sometimes open a writer against a closing core.
|
|
30
|
+
// Ignore assertion errors from Autobase writer open during that window.
|
|
31
|
+
if (err?.name === 'AssertionError') return;
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Hypercore/Hyperbee can throw SESSION_CLOSED while the core is shutting down.
|
|
37
|
+
// Swallow those during tests to avoid teardown flakes on slower runners.
|
|
38
|
+
const originalSnapshot = Hypercore.prototype.snapshot;
|
|
39
|
+
Hypercore.prototype.snapshot = function patchedSnapshot(...args) {
|
|
40
|
+
try {
|
|
41
|
+
return originalSnapshot.apply(this, args);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (err?.code === 'SESSION_CLOSED') return this;
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const originalCoreGet = Hypercore.prototype.get;
|
|
49
|
+
Hypercore.prototype.get = async function patchedCoreGet(...args) {
|
|
50
|
+
try {
|
|
51
|
+
return await originalCoreGet.apply(this, args);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (err?.code === 'SESSION_CLOSED') return null;
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const originalMakeSnapshot = Hyperbee.prototype._makeSnapshot;
|
|
59
|
+
Hyperbee.prototype._makeSnapshot = function patchedMakeSnapshot(...args) {
|
|
60
|
+
try {
|
|
61
|
+
return originalMakeSnapshot.apply(this, args);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
if (err?.code === 'SESSION_CLOSED') return this.core;
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
22
68
|
export const encryptionKey = argv?.includes('--encrypt-all')
|
|
23
69
|
? b4a.alloc(32).fill('autobase-encryption-test')
|
|
24
70
|
: undefined;
|
|
@@ -288,7 +334,7 @@ export function deriveIndexerSequenceState(base) {
|
|
|
288
334
|
.map(entry => entry?.key)
|
|
289
335
|
.filter(key => key && key.length > 0);
|
|
290
336
|
const concatenated = buffers.length > 0 ? b4a.concat(buffers) : b4a.alloc(0);
|
|
291
|
-
return
|
|
337
|
+
return PeerWallet.blake3(concatenated);
|
|
292
338
|
}
|
|
293
339
|
|
|
294
340
|
let osModule;
|
|
@@ -6,17 +6,17 @@ import path from 'path';
|
|
|
6
6
|
import CompleteStateMessageOperations from '../../src/messages/completeStateMessages/CompleteStateMessageOperations.js'
|
|
7
7
|
import PartialStateMessageOperations from '../../src/messages/partialStateMessages/PartialStateMessageOperations.js';
|
|
8
8
|
import {MainSettlementBus} from '../../src/index.js'
|
|
9
|
+
import { createConfig, ENV } from '../../src/config/env.js'
|
|
9
10
|
import fileUtils from '../../src/utils/fileUtils.js'
|
|
10
11
|
import {EntryType} from '../../src/utils/constants.js';
|
|
11
12
|
import {sleep} from '../../src/utils/helpers.js'
|
|
12
13
|
import {formatIndexersEntry} from '../../src/utils/helpers.js';
|
|
13
|
-
import {blake3Hash} from '../../src/utils/crypto.js';
|
|
14
14
|
import CompleteStateMessageBuilder from '../../src/messages/completeStateMessages/CompleteStateMessageBuilder.js'
|
|
15
15
|
import CompleteStateMessageDirector from '../../src/messages/completeStateMessages/CompleteStateMessageDirector.js'
|
|
16
16
|
import { safeEncodeApplyOperation } from "../../src/utils/protobuf/operationHelpers.js"
|
|
17
17
|
import { $TNK } from '../../src/core/state/utils/balance.js';
|
|
18
|
-
import { operation } from 'trac-crypto-api'
|
|
19
18
|
import { EventType } from '../../src/utils/constants.js';
|
|
19
|
+
import { Config } from '../../src/config/config.js';
|
|
20
20
|
let os, fsp;
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -70,7 +70,7 @@ export const tick = () => new Promise(resolve => setImmediate(resolve));
|
|
|
70
70
|
export async function fundPeer(admin, toFund, amount) {
|
|
71
71
|
const txValidity = await admin.msb.state.getIndexerSequenceState()
|
|
72
72
|
const director = new CompleteStateMessageDirector();
|
|
73
|
-
director.builder = new CompleteStateMessageBuilder(admin.wallet);
|
|
73
|
+
director.builder = new CompleteStateMessageBuilder(admin.wallet, admin.config);
|
|
74
74
|
const payload = await director.buildBalanceInitializationMessage(
|
|
75
75
|
admin.wallet.address,
|
|
76
76
|
toFund.wallet.address,
|
|
@@ -88,9 +88,10 @@ export async function fundPeer(admin, toFund, amount) {
|
|
|
88
88
|
export async function initMsbPeer(peerName, peerKeyPair, temporaryDirectory, options = {}) {
|
|
89
89
|
const peer = await initDirectoryStructure(peerName, peerKeyPair, temporaryDirectory);
|
|
90
90
|
peer.options = options
|
|
91
|
-
peer.options.
|
|
92
|
-
peer.options.
|
|
93
|
-
|
|
91
|
+
peer.options.storesDirectory = peer.storesDirectory;
|
|
92
|
+
peer.options.storeName = peer.storeName;
|
|
93
|
+
peer.config = createConfig(ENV.DEVELOPMENT, peer.options)
|
|
94
|
+
const msb = new MainSettlementBus(peer.config);
|
|
94
95
|
|
|
95
96
|
peer.msb = msb;
|
|
96
97
|
peer.wallet = msb.wallet;
|
|
@@ -110,10 +111,11 @@ export async function initMsbAdmin(keyPair, temporaryDirectory, options = {}) {
|
|
|
110
111
|
const admin = await initMsbPeer(peerName, keyPair, temporaryDirectory, { ...options, bootstrap: randomBytes(32).toString('hex') });
|
|
111
112
|
|
|
112
113
|
await admin.msb.ready();
|
|
113
|
-
admin.options.bootstrap = admin.msb.state.writingKey;
|
|
114
|
+
admin.options.bootstrap = admin.msb.state.writingKey.toString('hex');
|
|
115
|
+
admin.config = new Config(admin.options, admin.config)
|
|
114
116
|
await admin.msb.close();
|
|
115
117
|
|
|
116
|
-
admin.msb = new MainSettlementBus(admin.
|
|
118
|
+
admin.msb = new MainSettlementBus(admin.config);
|
|
117
119
|
await admin.msb.ready();
|
|
118
120
|
await admin.msb.state.append(null); // before initialization system.indexers is empty, we need to initialize first block to create system.indexers array
|
|
119
121
|
return admin;
|
|
@@ -122,7 +124,9 @@ export async function initMsbAdmin(keyPair, temporaryDirectory, options = {}) {
|
|
|
122
124
|
export async function setupMsbAdmin(keyPair, temporaryDirectory, options = {}) {
|
|
123
125
|
const admin = await initMsbAdmin(keyPair, temporaryDirectory, options);
|
|
124
126
|
const txValidity = await admin.msb.state.getIndexerSequenceState();
|
|
125
|
-
const addAdminMessage = await CompleteStateMessageOperations
|
|
127
|
+
const addAdminMessage = await new CompleteStateMessageOperations(admin.wallet, admin.config)
|
|
128
|
+
.assembleAddAdminMessage(admin.msb.state.writingKey, txValidity);
|
|
129
|
+
|
|
126
130
|
await admin.msb.state.append(addAdminMessage);
|
|
127
131
|
await tick();
|
|
128
132
|
return admin;
|
|
@@ -133,21 +137,21 @@ export async function setupNodeAsWriter(admin, writerCandidate) {
|
|
|
133
137
|
await setupWhitelist(admin, [writerCandidate.wallet.address]); // ensure if is whitelisted
|
|
134
138
|
|
|
135
139
|
const validity = await admin.msb.getIndexerSequenceState()
|
|
136
|
-
const req = await PartialStateMessageOperations.
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
const req = await new PartialStateMessageOperations(writerCandidate.wallet, admin.config)
|
|
141
|
+
.assembleAddWriterMessage(
|
|
142
|
+
b4a.toString(writerCandidate.msb.state.writingKey, 'hex'),
|
|
143
|
+
b4a.toString(validity, 'hex'));
|
|
140
144
|
|
|
141
145
|
await waitWritable(admin, writerCandidate, async () => {
|
|
142
|
-
const raw = await CompleteStateMessageOperations.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
146
|
+
const raw = await new CompleteStateMessageOperations(admin.wallet, admin.config)
|
|
147
|
+
.assembleAddWriterMessage(
|
|
148
|
+
admin.wallet.address,
|
|
149
|
+
b4a.from(req.rao.tx, 'hex'),
|
|
150
|
+
b4a.from(req.rao.txv, 'hex'),
|
|
151
|
+
b4a.from(req.rao.iw, 'hex'),
|
|
152
|
+
b4a.from(req.rao.in, 'hex'),
|
|
153
|
+
b4a.from(req.rao.is, 'hex')
|
|
154
|
+
)
|
|
151
155
|
await admin.msb.state.append(raw)
|
|
152
156
|
})
|
|
153
157
|
|
|
@@ -168,21 +172,21 @@ export async function promoteToWriter(admin, writerCandidate) {
|
|
|
168
172
|
isIndexer: false,
|
|
169
173
|
})
|
|
170
174
|
const validity = await admin.msb.state.getIndexerSequenceState()
|
|
171
|
-
const req = await PartialStateMessageOperations.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
const req = await new PartialStateMessageOperations(writerCandidate.wallet, writerCandidate.config)
|
|
176
|
+
.assembleAddWriterMessage(
|
|
177
|
+
b4a.toString(writerCandidate.msb.state.writingKey, 'hex'),
|
|
178
|
+
b4a.toString(validity, 'hex'));
|
|
175
179
|
|
|
176
180
|
await waitWritable(writerCandidate, writerCandidate, async () => {
|
|
177
|
-
const raw = await CompleteStateMessageOperations.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
181
|
+
const raw = await new CompleteStateMessageOperations(admin.wallet, admin.config)
|
|
182
|
+
.assembleAddWriterMessage(
|
|
183
|
+
req.address,
|
|
184
|
+
b4a.from(req.rao.tx, 'hex'),
|
|
185
|
+
b4a.from(req.rao.txv, 'hex'),
|
|
186
|
+
b4a.from(req.rao.iw, 'hex'),
|
|
187
|
+
b4a.from(req.rao.in, 'hex'),
|
|
188
|
+
b4a.from(req.rao.is, 'hex')
|
|
189
|
+
)
|
|
186
190
|
await admin.msb.state.append(raw)
|
|
187
191
|
})
|
|
188
192
|
|
|
@@ -201,8 +205,10 @@ export async function setupMsbWriter(admin, peerName, peerKeyPair, temporaryDire
|
|
|
201
205
|
|
|
202
206
|
export async function setupMsbIndexer(indexerCandidate, admin) {
|
|
203
207
|
try {
|
|
204
|
-
|
|
205
|
-
|
|
208
|
+
const validity = await admin.msb.state.getIndexerSequenceState()
|
|
209
|
+
const req = await new CompleteStateMessageOperations(admin.wallet, admin.config)
|
|
210
|
+
.assembleAddIndexerMessage(indexerCandidate.wallet.address, validity);
|
|
211
|
+
|
|
206
212
|
await admin.msb.state.append(req);
|
|
207
213
|
await tick(); // wait for the request to be processed
|
|
208
214
|
|
|
@@ -211,7 +217,7 @@ export async function setupMsbIndexer(indexerCandidate, admin) {
|
|
|
211
217
|
if (!indexersEntry) {
|
|
212
218
|
return false;
|
|
213
219
|
}
|
|
214
|
-
const formatted = formatIndexersEntry(indexersEntry);
|
|
220
|
+
const formatted = formatIndexersEntry(indexersEntry, admin.config.addressLength);
|
|
215
221
|
if (!formatted || !formatted.addresses) return false;
|
|
216
222
|
return formatted.addresses.includes(indexerCandidate.wallet.address);
|
|
217
223
|
}
|
|
@@ -254,11 +260,13 @@ export async function setupWhitelist(admin, whitelistAddresses) {
|
|
|
254
260
|
fileUtils.readAddressesFromWhitelistFile = async () => whitelistAddresses;
|
|
255
261
|
const validity = await admin.msb.state.getIndexerSequenceState()
|
|
256
262
|
for (const address of whitelistAddresses) {
|
|
257
|
-
const msg = await CompleteStateMessageOperations
|
|
263
|
+
const msg = await new CompleteStateMessageOperations(admin.wallet, admin.config)
|
|
264
|
+
.assembleAppendWhitelistMessages(validity, address);
|
|
265
|
+
|
|
258
266
|
await admin.msb.state.append(msg);
|
|
259
267
|
await sleep(100)
|
|
260
268
|
}
|
|
261
|
-
|
|
269
|
+
|
|
262
270
|
fileUtils.readAddressesFromWhitelistFile = originalReadAddressesFromWhitelistFile;
|
|
263
271
|
}
|
|
264
272
|
|
|
@@ -306,23 +314,23 @@ export async function initDirectoryStructure(peerName, keyPair, temporaryDirecto
|
|
|
306
314
|
export const deployExternalBootstrap = async (writer, externalNode) => {
|
|
307
315
|
const externalBootstrap = randomBytes(32).toString('hex');
|
|
308
316
|
const txValidity = await writer.msb.state.getIndexerSequenceState();
|
|
309
|
-
const payload = await PartialStateMessageOperations.
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const raw = await CompleteStateMessageOperations.
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
317
|
+
const payload = await new PartialStateMessageOperations(externalNode.msb.wallet, admin.config)
|
|
318
|
+
.assembleBootstrapDeploymentMessage(
|
|
319
|
+
externalBootstrap,
|
|
320
|
+
randomBytes(32).toString('hex'),
|
|
321
|
+
txValidity.toString('hex')
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
const raw = await new CompleteStateMessageOperations(writer.msb.wallet, admin.config)
|
|
325
|
+
.assembleCompleteBootstrapDeployment(
|
|
326
|
+
payload.address,
|
|
327
|
+
b4a.from(payload.bdo.tx, 'hex'),
|
|
328
|
+
b4a.from(payload.bdo.txv, 'hex'),
|
|
329
|
+
b4a.from(payload.bdo.bs, 'hex'),
|
|
330
|
+
b4a.from(payload.bdo.ic, 'hex'),
|
|
331
|
+
b4a.from(payload.bdo.in, 'hex'),
|
|
332
|
+
b4a.from(payload.bdo.is, 'hex'),
|
|
333
|
+
)
|
|
326
334
|
await writer.msb.state.base.append(raw)
|
|
327
335
|
await tick()
|
|
328
336
|
await waitForHash(writer, payload.bdo.tx)
|
|
@@ -343,29 +351,29 @@ export const generatePostTx = async (writer, externalNode, externalContractBoots
|
|
|
343
351
|
}
|
|
344
352
|
};
|
|
345
353
|
|
|
346
|
-
const contentHash = await
|
|
354
|
+
const contentHash = await PeerWallet.blake3(JSON.stringify(testObj));
|
|
347
355
|
const validity = await writer.msb.state.getIndexerSequenceState()
|
|
348
|
-
const tx = await PartialStateMessageOperations.
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const postTx = await CompleteStateMessageOperations.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
356
|
+
const tx = await new PartialStateMessageOperations(externalNode.wallet, admin.config)
|
|
357
|
+
.assembleTransactionOperationMessage(
|
|
358
|
+
peerWriterKey,
|
|
359
|
+
b4a.toString(validity, 'hex'),
|
|
360
|
+
b4a.toString(contentHash, 'hex'),
|
|
361
|
+
externalContractBootstrap,
|
|
362
|
+
b4a.toString(writer.msb.bootstrap, 'hex')
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
const postTx = await new CompleteStateMessageOperations(writer.wallet, admin.config)
|
|
366
|
+
.assembleCompleteTransactionOperationMessage(
|
|
367
|
+
tx.address,
|
|
368
|
+
b4a.from(tx.txo.tx, 'hex'),
|
|
369
|
+
b4a.from(tx.txo.txv, 'hex'),
|
|
370
|
+
b4a.from(tx.txo.iw, 'hex'),
|
|
371
|
+
b4a.from(tx.txo.in, 'hex'),
|
|
372
|
+
b4a.from(tx.txo.ch, 'hex'),
|
|
373
|
+
b4a.from(tx.txo.is, 'hex'),
|
|
374
|
+
b4a.from(tx.txo.bs, 'hex'),
|
|
375
|
+
b4a.from(tx.txo.mbs, 'hex')
|
|
376
|
+
);
|
|
369
377
|
|
|
370
378
|
return { postTx, txHash: tx.txo.tx };
|
|
371
379
|
}
|
|
@@ -404,7 +412,6 @@ export const tryToSyncWriters = async (...args) => {
|
|
|
404
412
|
}
|
|
405
413
|
}
|
|
406
414
|
|
|
407
|
-
|
|
408
415
|
export async function waitForNotIndexer(indexer) {
|
|
409
416
|
try {
|
|
410
417
|
let attempts = 0;
|
|
@@ -417,7 +424,7 @@ export async function waitForNotIndexer(indexer) {
|
|
|
417
424
|
if (!indexersEntry) {
|
|
418
425
|
notIndexer = true;
|
|
419
426
|
} else {
|
|
420
|
-
const formatted = formatIndexersEntry(indexersEntry);
|
|
427
|
+
const formatted = formatIndexersEntry(indexersEntry, admin.config.addressLength);
|
|
421
428
|
if (!formatted || !formatted.addresses) {
|
|
422
429
|
notIndexer = true;
|
|
423
430
|
} else if (!formatted.addresses.includes(indexer.wallet.address)) {
|
|
@@ -564,7 +571,7 @@ export async function waitForIndexersEntry(node, expected) {
|
|
|
564
571
|
await sleep(250);
|
|
565
572
|
continue;
|
|
566
573
|
}
|
|
567
|
-
const formatted = formatIndexersEntry(indexersEntry);
|
|
574
|
+
const formatted = formatIndexersEntry(indexersEntry, admin.config.addressLength);
|
|
568
575
|
if (formatted && formatted.addresses && formatted.addresses.includes(expected.address)) {
|
|
569
576
|
break;
|
|
570
577
|
}
|
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import b4a from "b4a";
|
|
2
2
|
import tracCrypto from "trac-crypto-api";
|
|
3
|
-
|
|
3
|
+
import PeerWallet from "trac-wallet";
|
|
4
4
|
import { $TNK } from "../../src/core/state/utils/balance.js";
|
|
5
5
|
import { createMessage } from "../../src/utils/buffer.js";
|
|
6
|
-
import {
|
|
7
|
-
import { OperationType, NETWORK_ID } from "../../src/utils/constants.js";
|
|
6
|
+
import { OperationType } from "../../src/utils/constants.js";
|
|
8
7
|
import { addressToBuffer } from "../../src/core/state/utils/address.js";
|
|
8
|
+
import { config } from '../helpers/config.js'
|
|
9
|
+
import { sleep } from "../../src/utils/helpers.js";
|
|
10
|
+
|
|
11
|
+
export const waitForConnection = async node => {
|
|
12
|
+
let attempts = 0
|
|
13
|
+
while (attempts < 60) {
|
|
14
|
+
const count = node.network.validatorConnectionManager.connectionCount()
|
|
15
|
+
if (count > 0) {
|
|
16
|
+
break
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
await sleep(300);
|
|
20
|
+
attempts++;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
9
23
|
|
|
10
24
|
/**
|
|
11
25
|
* Build a base64-encoded transfer payload and matching tx hash
|
|
@@ -15,18 +29,18 @@ import { addressToBuffer } from "../../src/core/state/utils/address.js";
|
|
|
15
29
|
* PartialOperation.validateSignature, so that tests broadcast
|
|
16
30
|
* transactions the node will accept without touching consensus code.
|
|
17
31
|
*
|
|
18
|
-
* @param {
|
|
32
|
+
* @param {object} context - General context
|
|
19
33
|
* @param {import("../../src/core/state/State.js").default} state - MSB state instance.
|
|
20
34
|
* @param {bigint} [amountTnk=1n] - Transfer amount in TNK units.
|
|
21
35
|
* @returns {Promise<{ payload: string, txHashHex: string }>}
|
|
22
36
|
*/
|
|
23
|
-
export async function buildRpcSelfTransferPayload(
|
|
37
|
+
export async function buildRpcSelfTransferPayload(context, state, amountTnk = 1n) {
|
|
24
38
|
const txvBuffer = await state.getIndexerSequenceState();
|
|
25
39
|
const txvHex = b4a.toString(txvBuffer, "hex");
|
|
26
40
|
|
|
27
41
|
const txData = await tracCrypto.transaction.preBuild(
|
|
28
|
-
wallet.address,
|
|
29
|
-
wallet.address,
|
|
42
|
+
context.wallet.address,
|
|
43
|
+
context.wallet.address,
|
|
30
44
|
b4a.toString($TNK(amountTnk), "hex"),
|
|
31
45
|
txvHex
|
|
32
46
|
);
|
|
@@ -38,10 +52,10 @@ export async function buildRpcSelfTransferPayload(wallet, state, amountTnk = 1n)
|
|
|
38
52
|
const txvBuf = b4a.from(txData.validity, "hex");
|
|
39
53
|
const nonceBuf = b4a.from(nonceHex, "hex");
|
|
40
54
|
const amountBuf = b4a.from(amountHex, "hex");
|
|
41
|
-
const toBuf = addressToBuffer(toAddress);
|
|
55
|
+
const toBuf = addressToBuffer(toAddress, config.addressPrefix);
|
|
42
56
|
|
|
43
57
|
const message = createMessage(
|
|
44
|
-
|
|
58
|
+
config.networkId,
|
|
45
59
|
txvBuf,
|
|
46
60
|
toBuf,
|
|
47
61
|
amountBuf,
|
|
@@ -49,12 +63,12 @@ export async function buildRpcSelfTransferPayload(wallet, state, amountTnk = 1n)
|
|
|
49
63
|
OperationType.TRANSFER
|
|
50
64
|
);
|
|
51
65
|
|
|
52
|
-
const messageHash = await
|
|
53
|
-
const signature = wallet.sign(messageHash);
|
|
66
|
+
const messageHash = await PeerWallet.blake3(message);
|
|
67
|
+
const signature = context.wallet.sign(messageHash);
|
|
54
68
|
|
|
55
69
|
const payloadObject = {
|
|
56
70
|
type: OperationType.TRANSFER,
|
|
57
|
-
address: wallet.address,
|
|
71
|
+
address: context.wallet.address,
|
|
58
72
|
tro: {
|
|
59
73
|
tx: b4a.toString(messageHash, "hex"),
|
|
60
74
|
txv: txData.validity,
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '../../../helpers/setupApplyTests.js';
|
|
6
6
|
import {randomBytes} from '../../../helpers/setupApplyTests.js';
|
|
7
7
|
import CompleteStateMessageOperations from '../../../../src/messages/completeStateMessages/CompleteStateMessageOperations.js';
|
|
8
|
+
import { config } from '../../../helpers/config.js';
|
|
8
9
|
import {testKeyPair1} from '../../../fixtures/apply.fixtures.js';
|
|
9
10
|
import b4a from 'b4a';
|
|
10
11
|
import { ADMIN_INITIAL_BALANCE } from '../../../../src/utils/constants.js';
|
|
@@ -17,11 +18,11 @@ let randomChannel;
|
|
|
17
18
|
|
|
18
19
|
const sendAddAdmin = async (invoker) => {
|
|
19
20
|
const validity = b4a.from(await admin.msb.state.getIndexerSequenceState(), 'hex')
|
|
20
|
-
const addAdminMessage = await CompleteStateMessageOperations.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
const addAdminMessage = await new CompleteStateMessageOperations(admin.wallet, config)
|
|
22
|
+
.assembleAddAdminMessage(
|
|
23
|
+
admin.msb.state.writingKey,
|
|
24
|
+
validity
|
|
25
|
+
);
|
|
25
26
|
|
|
26
27
|
// add admin to base
|
|
27
28
|
await invoker.msb.state.append(addAdminMessage); // Send `add admin` request to apply function
|
|
@@ -30,11 +31,11 @@ const sendAddAdmin = async (invoker) => {
|
|
|
30
31
|
hook('Initialize admin for addAdmin tests', async () => {
|
|
31
32
|
randomChannel = randomBytes(32).toString('hex');
|
|
32
33
|
const baseOptions = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
enableTxApplyLogs: false,
|
|
35
|
+
enableInteractiveMode: false,
|
|
36
|
+
enableRoleRequester: false,
|
|
36
37
|
channel: randomChannel,
|
|
37
|
-
|
|
38
|
+
enableValidatorObserver: false,
|
|
38
39
|
}
|
|
39
40
|
tmpDirectory = await initTemporaryDirectory();
|
|
40
41
|
admin = await initMsbAdmin(testKeyPair1, tmpDirectory, baseOptions);
|
|
@@ -11,6 +11,7 @@ import {testKeyPair1, testKeyPair2, testKeyPair3, testKeyPair4} from '../../../f
|
|
|
11
11
|
import b4a from 'b4a';
|
|
12
12
|
import { decode as decodeAdmin } from '../../../../src/core/state/utils/adminEntry.js';
|
|
13
13
|
import { EntryType } from '../../../../src/utils/constants.js';
|
|
14
|
+
import { config } from '../../../helpers/config.js';
|
|
14
15
|
//TODO: ADD TEST WHEN NON-ADMIN NODE FORGES ADD ADMIN OPERATION AND BROADCASTS IT TO THE STATE - SHOULD BE REJECTED
|
|
15
16
|
|
|
16
17
|
let admin, newAdmin;
|
|
@@ -21,11 +22,11 @@ let randomChannel;
|
|
|
21
22
|
hook('Initialize admin for addAdmin tests', async () => {
|
|
22
23
|
randomChannel = randomBytes(32).toString('hex');
|
|
23
24
|
const baseOptions = {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
enableTxApplyLogs: false,
|
|
26
|
+
enableInteractiveMode: false,
|
|
27
|
+
enableRoleRequester: false,
|
|
27
28
|
channel: randomChannel,
|
|
28
|
-
|
|
29
|
+
enableValidatorObserver: false,
|
|
29
30
|
}
|
|
30
31
|
tmpDirectory = await initTemporaryDirectory()
|
|
31
32
|
admin = await setupMsbAdmin(testKeyPair1, tmpDirectory, baseOptions);
|
|
@@ -87,24 +88,24 @@ test('Apply function addAdmin for recovery - happy path', async (k) => {
|
|
|
87
88
|
await newAdmin.msb.ready();
|
|
88
89
|
await newAdmin.msb.state.append(null);
|
|
89
90
|
const validity = b4a.toString(await newAdmin.msb.state.getIndexerSequenceState(), 'hex')
|
|
90
|
-
const addAdminMessage = await PartialStateMessageOperations.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
const addAdminMessage = await new PartialStateMessageOperations(newAdmin.wallet, config)
|
|
92
|
+
.assembleAdminRecoveryMessage(
|
|
93
|
+
b4a.toString(newAdmin.msb.state.writingKey, 'hex'),
|
|
94
|
+
validity
|
|
95
|
+
);
|
|
95
96
|
|
|
96
|
-
const rawTx = await CompleteStateMessageOperations.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
97
|
+
const rawTx = await new CompleteStateMessageOperations(writer.wallet, config)
|
|
98
|
+
.assembleAdminRecoveryMessage(
|
|
99
|
+
addAdminMessage.address,
|
|
100
|
+
b4a.from(addAdminMessage.rao.tx, 'hex'),
|
|
101
|
+
b4a.from(addAdminMessage.rao.txv, 'hex'),
|
|
102
|
+
b4a.from(addAdminMessage.rao.iw, 'hex'),
|
|
103
|
+
b4a.from(addAdminMessage.rao.in, 'hex'),
|
|
104
|
+
b4a.from(addAdminMessage.rao.is, 'hex')
|
|
105
|
+
)
|
|
105
106
|
await writer.msb.state.append(rawTx)
|
|
106
107
|
await tryToSyncWriters(writer, indexer1, indexer2, newAdmin);
|
|
107
|
-
const adminEntryAfter = decodeAdmin(await writer.msb.state.get(EntryType.ADMIN)); // check if the admin entry was added successfully in the base
|
|
108
|
+
const adminEntryAfter = decodeAdmin(await writer.msb.state.get(EntryType.ADMIN), config.addressPrefix); // check if the admin entry was added successfully in the base
|
|
108
109
|
k.ok(adminEntryAfter, 'Result should not be null');
|
|
109
110
|
k.ok(adminEntryAfter.address === newAdmin.wallet.address, 'New Admin address in base should match new admin wallet address');
|
|
110
111
|
k.ok(adminAddressBeforeRecovery === newAdmin.wallet.address, 'New Admin wallet address should be the same as old admin wallet address');
|