Skip to content

Commit 11c138b

Browse files
perf(snapshot): improve snapshot import performance (#954)
* fix CODECOV_TOKEN check * empty commit * precalculate eth address * batch import accounts and cold wallets * contracts: allow batch import of voters * batch import voters * fix configuration paths * add static config example * fix static snapshot export * update e2e snapshot fixtures * fix functional test * update test fixtures * style: resolve style guide violations * fix e2e * use proper imports * style: resolve style guide violations * Remove console log --------- Co-authored-by: sebastijankuzner <sebastijan.kuzner@outlook.com>
1 parent 9ffb36a commit 11c138b

48 files changed

Lines changed: 2237 additions & 2073 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

contracts/src/consensus/ConsensusV1.sol

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,15 @@ contract ConsensusV1 is UUPSUpgradeable, OwnableUpgradeable {
150150
emit ValidatorRegistered(addr, blsPublicKey);
151151
}
152152

153-
function addVote(address voter, address validator) external onlyOwner {
153+
function addVotes(address[] calldata voters, address[] calldata validators) external onlyOwner {
154+
require(voters.length == validators.length, "input length mismatch");
155+
156+
for (uint256 i = 0; i < voters.length; i++) {
157+
_addVote(voters[i], validators[i]);
158+
}
159+
}
160+
161+
function _addVote(address voter, address validator) internal {
154162
if (_rounds.length > 0) {
155163
revert ImportIsNotAllowed();
156164
}

contracts/test/consensus/Consensus-VoteAdd.sol

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,12 @@ contract ConsensusTest is Base {
2525
// Vote
2626
vm.expectEmit(address(consensus));
2727
emit ConsensusV1.Voted(voterAddr, addr);
28-
consensus.addVote(voterAddr, addr);
28+
address[] memory voters = new address[](1);
29+
voters[0] = voterAddr;
30+
address[] memory validators = new address[](1);
31+
validators[0] = addr;
32+
33+
consensus.addVotes(voters, validators);
2934

3035
// Assert validator
3136
ConsensusV1.Validator memory validator = consensus.getValidator(addr);
@@ -60,7 +65,11 @@ contract ConsensusTest is Base {
6065
// Vote
6166
vm.expectEmit(address(consensus));
6267
emit ConsensusV1.Voted(voterAddr, addr);
63-
consensus.addVote(voterAddr, addr);
68+
address[] memory voters = new address[](1);
69+
voters[0] = voterAddr;
70+
address[] memory validators = new address[](1);
71+
validators[0] = addr;
72+
consensus.addVotes(voters, validators);
6473

6574
// Assert validator
6675
ConsensusV1.Validator memory validator = consensus.getValidator(addr);
@@ -95,7 +104,11 @@ contract ConsensusTest is Base {
95104
// Vote
96105
vm.expectEmit(address(consensus));
97106
emit ConsensusV1.Voted(voterAddr, addr);
98-
consensus.addVote(voterAddr, addr);
107+
address[] memory voters = new address[](1);
108+
voters[0] = voterAddr;
109+
address[] memory validators = new address[](1);
110+
validators[0] = addr;
111+
consensus.addVotes(voters, validators);
99112

100113
// Assert validator
101114
ConsensusV1.Validator memory validator = consensus.getValidator(addr);
@@ -115,19 +128,30 @@ contract ConsensusTest is Base {
115128

116129
function test_add_vote_revert_if_caller_is_not_owner() public {
117130
address addr = address(1);
131+
address[] memory voters = new address[](1);
132+
voters[0] = addr;
133+
address[] memory validators = new address[](1);
134+
validators[0] = addr;
135+
118136
vm.startPrank(addr);
119137
vm.expectRevert(abi.encodeWithSelector(OwnableUpgradeable.OwnableUnauthorizedAccount.selector, addr));
120-
consensus.addVote(addr, addr);
138+
consensus.addVotes(voters, validators);
121139
}
122140

123141
function test_add_vote_revert_if_round_already_calculated() public {
124142
address addr = address(1);
143+
address[] memory voters = new address[](1);
144+
voters[0] = addr;
145+
address[] memory validators = new address[](1);
146+
validators[0] = addr;
147+
125148
consensus.addValidator(addr, prepareBLSKey(addr), false);
126149

127150
consensus.calculateActiveValidators(1);
128151

129152
vm.expectRevert(ConsensusV1.ImportIsNotAllowed.selector);
130-
consensus.addVote(addr, addr);
153+
154+
consensus.addVotes(voters, validators);
131155
}
132156

133157
function test_add_vote_allow_self_vote() public {
@@ -147,7 +171,12 @@ contract ConsensusTest is Base {
147171
// Vote
148172
vm.expectEmit(address(consensus));
149173
emit ConsensusV1.Voted(voterAddr, addr);
150-
consensus.addVote(voterAddr, addr);
174+
175+
address[] memory voters = new address[](1);
176+
voters[0] = voterAddr;
177+
address[] memory validators = new address[](1);
178+
validators[0] = addr;
179+
consensus.addVotes(voters, validators);
151180
vm.stopPrank();
152181

153182
// Assert voteBalance
@@ -173,19 +202,30 @@ contract ConsensusTest is Base {
173202
// Prepare voter
174203
address voterAddr = address(2);
175204

205+
address[] memory voters = new address[](1);
206+
voters[0] = voterAddr;
207+
address[] memory validators = new address[](1);
208+
validators[0] = addr;
209+
176210
vm.expectEmit(address(consensus));
177211
emit ConsensusV1.Voted(voterAddr, addr);
178-
consensus.addVote(voterAddr, addr);
212+
213+
consensus.addVotes(voters, validators);
179214

180215
vm.expectRevert(ConsensusV1.AlreadyVoted.selector);
181-
consensus.addVote(voterAddr, addr);
216+
consensus.addVotes(voters, validators);
182217
}
183218

184219
function test_add_vote_prevent_vote_for_unregistered_validator() public {
185220
address addr = address(1);
186221

222+
address[] memory voters = new address[](1);
223+
voters[0] = addr;
224+
address[] memory validators = new address[](1);
225+
validators[0] = addr;
226+
187227
vm.expectRevert(ConsensusV1.ValidatorNotRegistered.selector);
188-
consensus.addVote(addr, addr);
228+
consensus.addVotes(voters, validators);
189229
}
190230

191231
function test_multiple_voted_different_validators() public {
@@ -205,17 +245,24 @@ contract ConsensusTest is Base {
205245
// Vote 1
206246
address voterAddr1 = address(11);
207247
vm.deal(voterAddr1, 100 ether);
208-
consensus.addVote(voterAddr1, validatorAddr1);
209248

210249
// Vote 2
211250
address voterAddr2 = address(12);
212251
vm.deal(voterAddr2, 100 ether);
213-
consensus.addVote(voterAddr2, validatorAddr2);
214252

215253
// Vote 3
216254
address voterAddr3 = address(13);
217255
vm.deal(voterAddr3, 100 ether);
218-
consensus.addVote(voterAddr3, validatorAddr3);
256+
257+
address[] memory voters = new address[](3);
258+
voters[0] = voterAddr1;
259+
voters[1] = voterAddr2;
260+
voters[2] = voterAddr3;
261+
address[] memory validators = new address[](3);
262+
validators[0] = validatorAddr1;
263+
validators[1] = validatorAddr2;
264+
validators[2] = validatorAddr3;
265+
consensus.addVotes(voters, validators);
219266

220267
// Assert validators 1
221268
ConsensusV1.Validator memory validator1 = consensus.getValidator(validatorAddr1);
@@ -258,17 +305,24 @@ contract ConsensusTest is Base {
258305
// Vote 1
259306
address voterAddr1 = address(11);
260307
vm.deal(voterAddr1, 100 ether);
261-
consensus.addVote(voterAddr1, validatorAddr1);
262308

263309
// Vote 2
264310
address voterAddr2 = address(12);
265311
vm.deal(voterAddr2, 100 ether);
266-
consensus.addVote(voterAddr2, validatorAddr1);
267312

268313
// Vote 3
269314
address voterAddr3 = address(13);
270315
vm.deal(voterAddr3, 100 ether);
271-
consensus.addVote(voterAddr3, validatorAddr1);
316+
317+
address[] memory voters = new address[](3);
318+
voters[0] = voterAddr1;
319+
voters[1] = voterAddr2;
320+
voters[2] = voterAddr3;
321+
address[] memory validators = new address[](3);
322+
validators[0] = validatorAddr1;
323+
validators[1] = validatorAddr1;
324+
validators[2] = validatorAddr1;
325+
consensus.addVotes(voters, validators);
272326

273327
// Assert validators 1
274328
ConsensusV1.Validator memory validator1 = consensus.getValidator(validatorAddr1);

packages/configuration-generator/source/application-factory.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { readFileSync } from "node:fs";
2+
13
import { Container } from "@mainsail/container";
24
import { Contracts, Identifiers } from "@mainsail/contracts";
35
import { ServiceProvider as CoreCryptoAddressBase58 } from "@mainsail/crypto-address-base58";
@@ -20,6 +22,7 @@ import { Application, Providers } from "@mainsail/kernel";
2022
import { ServiceProvider as CoreSerializer } from "@mainsail/serializer";
2123
import { ServiceProvider as CoreSnapshotLegacyImporter } from "@mainsail/snapshot-legacy-importer";
2224
import { ServiceProvider as CoreValidation } from "@mainsail/validation";
25+
import { readJSONSync } from "fs-extra/esm";
2326
import { dirSync, setGracefulCleanup } from "tmp";
2427

2528
import { ConfigurationGenerator } from "./configuration-generator.js";
@@ -50,10 +53,10 @@ export const makeApplication = async (configurationPath: string, options: Record
5053
warning: (message: string) => console.log(message),
5154
});
5255
// Used for evm instance
53-
const fsExtra = await import("fs-extra/esm");
5456
app.bind(Identifiers.Services.Filesystem.Service).toConstantValue({
5557
existsSync: () => true,
56-
readJSONSync: (file: string, options?: Record<string, any>) => fsExtra.readJSONSync(file, options),
58+
get: (path: string) => readFileSync(path),
59+
readJSONSync: (file: string, options?: Record<string, any>) => readJSONSync(file, options),
5760
});
5861
setGracefulCleanup();
5962
app.rebind("path.data").toConstantValue(dirSync().name);

packages/configuration-generator/source/configuration-generator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ export class ConfigurationGenerator {
212212
}
213213

214214
ensureDirSync(join(this.configurationPath, "snapshot"));
215-
this.configurationWriter.writeSnapshot(options.snapshot.path, options.snapshot.snapshotHash);
215+
this.configurationWriter.writeSnapshot(options.snapshot.path);
216216
},
217217
title: `Writing snapshot.json in core config path.`,
218218
});

packages/configuration-generator/source/configuration-writer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ export class ConfigurationWriter {
6969
);
7070
}
7171

72-
writeSnapshot(snapshotPath: string, snapshotHash: string): void {
72+
writeSnapshot(snapshotPath: string): void {
7373
snapshotPath = resolve(snapshotPath);
74-
copyFileSync(snapshotPath, path.join(this.configurationPath, "snapshot", `${snapshotHash}.json`));
74+
copyFileSync(snapshotPath, path.join(this.configurationPath, "snapshot", path.basename(snapshotPath)));
7575
}
7676
}

packages/contracts/source/contracts/evm/instance.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ export interface Instance extends CommitHandler {
2929
initializeGenesis(commit: GenesisInfo): Promise<void>;
3030
getAccountInfo(address: string, height?: bigint): Promise<AccountInfo>;
3131
getAccountInfoExtended(address: string, legacyAddress?: string): Promise<AccountInfoExtended>;
32-
importAccountInfo(info: AccountInfoExtended): Promise<void>;
33-
importLegacyColdWallet(wallet: ImportLegacyColdWallet): Promise<void>;
32+
importAccountInfos(infos: AccountInfoExtended[]): Promise<void>;
33+
importLegacyColdWallets(wallets: ImportLegacyColdWallet[]): Promise<void>;
3434
getAccounts(offset: bigint, limit: bigint): Promise<GetAccountsResult>;
3535
getLegacyAttributes(address: string, legacyAddress?: string): Promise<LegacyAttributes | null>;
3636
getLegacyColdWallets(offset: bigint, limit: bigint): Promise<GetLegacyColdWalletsResult>;

packages/evm-contracts/source/abis/ConsensusV1.json

Lines changed: 26 additions & 26 deletions
Large diffs are not rendered by default.

packages/evm-service/source/instances/evm.test.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,13 @@ describe<{
253253

254254
// Import legacy cold wallet with 10n balance
255255
await instance.prepareNextCommit({ commitKey });
256-
await instance.importLegacyColdWallet({
257-
address: legacyAddress,
258-
balance: 10n,
259-
legacyAttributes: {},
260-
});
256+
await instance.importLegacyColdWallets([
257+
{
258+
address: legacyAddress,
259+
balance: 10n,
260+
legacyAttributes: {},
261+
},
262+
]);
261263
await commit(commitKey);
262264

263265
assert.undefined((await instance.getLegacyColdWallets(0n, 100n)).wallets[0].mergeInfo);
@@ -358,11 +360,13 @@ describe<{
358360
} as any);
359361

360362
await instance.prepareNextCommit({ commitKey });
361-
await instance.importLegacyColdWallet({
362-
address: legacyAddress,
363-
balance: 999n,
364-
legacyAttributes: {},
365-
});
363+
await instance.importLegacyColdWallets([
364+
{
365+
address: legacyAddress,
366+
balance: 999n,
367+
legacyAttributes: {},
368+
},
369+
]);
366370
await commit(commitKey);
367371

368372
let { wallets } = await instance.getLegacyColdWallets(0n, 100n);

packages/evm-service/source/instances/evm.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,12 @@ export class EvmInstance implements Contracts.Evm.Instance, Contracts.Evm.Storag
108108
return this.#evm.getAccountInfoExtended(address, legacyAddress);
109109
}
110110

111-
public async importAccountInfo(info: Contracts.Evm.AccountInfoExtended): Promise<void> {
112-
return this.#evm.importAccountInfo(info);
111+
public async importAccountInfos(infos: Contracts.Evm.AccountInfoExtended[]): Promise<void> {
112+
return this.#evm.importAccountInfos(infos);
113113
}
114114

115-
public async importLegacyColdWallet(wallet: Contracts.Evm.ImportLegacyColdWallet): Promise<void> {
116-
return this.#evm.importLegacyColdWallet({ ...wallet, mergeInfo: undefined });
115+
public async importLegacyColdWallets(wallets: Contracts.Evm.ImportLegacyColdWallet[]): Promise<void> {
116+
return this.#evm.importLegacyColdWallets(wallets);
117117
}
118118

119119
public async getAccounts(offset: bigint, limit: bigint): Promise<Contracts.Evm.GetAccountsResult> {

0 commit comments

Comments
 (0)