Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: import v3 snapshot #793

Merged
merged 30 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
35208fd
legacy snapshot generator
oXtxNt9U Nov 25, 2024
2db708c
prepare genesis block generator
oXtxNt9U Nov 25, 2024
c71a78f
style: resolve style guide violations
oXtxNt9U Nov 25, 2024
d563e0e
fix deps
oXtxNt9U Nov 25, 2024
ee2a753
style: resolve style guide violations
oXtxNt9U Nov 25, 2024
92ccc47
update comments
oXtxNt9U Dec 3, 2024
eff9926
update interfaces
oXtxNt9U Dec 3, 2024
8297466
add `seedAccountInfo` to evm
oXtxNt9U Dec 3, 2024
70820a8
add snapshot importer package
oXtxNt9U Dec 3, 2024
e34874f
use snapshot importer for creating genesis block
oXtxNt9U Dec 3, 2024
6b9cdb2
support snapshot during genesis bootstrap
oXtxNt9U Dec 3, 2024
63bd7bc
set temporary path
oXtxNt9U Dec 3, 2024
d13e244
commit dirty lockfile
oXtxNt9U Dec 3, 2024
11d2c48
style: resolve style guide violations
oXtxNt9U Dec 3, 2024
54c587e
shared contract deployer
oXtxNt9U Dec 4, 2024
3b08ab3
style: resolve style guide violations
oXtxNt9U Dec 4, 2024
1992b50
seed usernames
oXtxNt9U Dec 4, 2024
ca74c81
style: resolve style guide violations
oXtxNt9U Dec 4, 2024
4ad6ed3
integrity checks
oXtxNt9U Dec 5, 2024
0050086
improve logging
oXtxNt9U Dec 5, 2024
e1494f1
style: resolve style guide violations
oXtxNt9U Dec 5, 2024
e87e716
fix tests
oXtxNt9U Dec 5, 2024
d7c9a87
make importer optional
oXtxNt9U Dec 5, 2024
c0317a5
fix check
oXtxNt9U Dec 5, 2024
64008b8
Merge branch 'develop' into feat/v3/snapshot-import
sebastijankuzner Dec 5, 2024
1a6acd4
Update pnpm-lock
sebastijankuzner Dec 5, 2024
5890961
typo
sebastijankuzner Dec 5, 2024
124de62
rename package
oXtxNt9U Dec 6, 2024
01f8c28
style: resolve style guide violations
oXtxNt9U Dec 6, 2024
f6f4bc7
call importer during bootstrap
oXtxNt9U Dec 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/api-database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
"@mainsail/kernel": "workspace:*",
"@mainsail/utils": "workspace:*",
"dayjs": "1.11.10",
"pg": "8.11.3",
"pg": "8.13.1",
"typeorm": "0.3.20"
},
"devDependencies": {
"@types/pg": "8.11.2",
"@types/pg": "8.11.10",
"uvu": "^0.5.6"
},
"engines": {
Expand Down
28 changes: 28 additions & 0 deletions packages/bootstrap/source/bootstrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export class Bootstrapper {
@optional()
private readonly apiSync?: Contracts.ApiSync.Service;

@inject(Identifiers.Snapshot.Legacy.Importer)
@optional()
private readonly snapshotImporter?: Contracts.Snapshot.LegacyImporter;

@inject(Identifiers.TransactionPool.Worker)
private readonly txPoolWorker!: Contracts.TransactionPool.Worker;

Expand Down Expand Up @@ -109,6 +113,7 @@ export class Bootstrapper {

async #initState(): Promise<void> {
if (this.databaseService.isEmpty()) {
await this.#tryImportSnapshot();
await this.#processGenesisBlock();
} else {
const commit = await this.databaseService.getLastCommit();
Expand Down Expand Up @@ -141,4 +146,27 @@ export class Bootstrapper {
await this.app.terminate(`Failed to process block at height ${commit.block.data.height}`, error);
}
}

async #tryImportSnapshot(): Promise<void> {
const genesisBlock = this.stateStore.getGenesisCommit();
const milestone = this.configuration.getMilestone(0);

// assume snapshot is present if the previous block points to a non-zero hash
if (
genesisBlock.block.header.previousBlock ===
"0000000000000000000000000000000000000000000000000000000000000000"
) {
if (milestone.snapshot) {
throw new Error("previous block set to snapshot but no hash in milestone");
}

return;
}

if (!this.snapshotImporter) {
throw new Error("snapshot importer not loaded");
}

await this.snapshotImporter.run(genesisBlock);
}
}
4 changes: 4 additions & 0 deletions packages/configuration-generator/bin/create-genesis-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ async function run() {
symbol: "TѦ",
token: "ARK",
distribute: true,
premine: "0",
snapshot: {
path: "../../snapshot-19a87c96dbe8ad1be06d33e97cd17f5662eb952c29efd3d8bb00c9c75e7582bc.json",
},
});
}

Expand Down
3 changes: 3 additions & 0 deletions packages/configuration-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@
"@mainsail/crypto-transaction-evm-call": "workspace:*",
"@mainsail/crypto-validation": "workspace:*",
"@mainsail/crypto-wif": "workspace:*",
"@mainsail/evm-consensus": "workspace:*",
"@mainsail/evm-contracts": "workspace:*",
"@mainsail/evm-gas-fee": "workspace:*",
"@mainsail/evm-service": "workspace:*",
"@mainsail/kernel": "workspace:*",
"@mainsail/serializer": "workspace:*",
"@mainsail/snapshot-legacy-exporter": "workspace:*",
"@mainsail/snapshot-legacy-importer": "workspace:*",
"@mainsail/utils": "workspace:*",
"@mainsail/validation": "workspace:*",
"bip39": "3.1.0",
Expand Down
13 changes: 12 additions & 1 deletion packages/configuration-generator/source/application-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ import { ServiceProvider as CoreCryptoTransaction } from "@mainsail/crypto-trans
import { ServiceProvider as CoreCryptoTransactionEvmCall } from "@mainsail/crypto-transaction-evm-call";
import { ServiceProvider as CoreCryptoValidation } from "@mainsail/crypto-validation";
import { ServiceProvider as CoreCryptoWif } from "@mainsail/crypto-wif";
import { ServiceProvider as CoreEvmConsensus } from "@mainsail/evm-consensus";
import { ServiceProvider as CoreEvmGasFee } from "@mainsail/evm-gas-fee";
import { ServiceProvider as EvmService } from "@mainsail/evm-service";
import { Application } from "@mainsail/kernel";
import { ServiceProvider as CoreSerializer } from "@mainsail/serializer";
import { ServiceProvider as CoreSnapshotLegacyImporter } from "@mainsail/snapshot-legacy-importer";
import { ServiceProvider as CoreValidation } from "@mainsail/validation";
import { dirSync, setGracefulCleanup } from "tmp";

Expand All @@ -40,10 +42,16 @@ export const makeApplication = async (configurationPath: string, options: Record
const app = new Application(new Container());
app.bind(Identifiers.Application.Name).toConstantValue(options.name);
app.bind(Identifiers.Services.EventDispatcher.Service).toConstantValue({});
app.bind(Identifiers.Services.Log.Service).toConstantValue({});
app.bind(Identifiers.Services.Log.Service).toConstantValue({
debug: (message: string) => console.log(message),
info: (message: string) => console.log(message),
warning: (message: string) => console.log(message),
});
// Used for evm instance
const fsExtra = await import("fs-extra/esm");
app.bind(Identifiers.Services.Filesystem.Service).toConstantValue({
existsSync: () => true,
readJSONSync: (file: string, options?: Record<string, any>) => fsExtra.readJSONSync(file, options),
});
setGracefulCleanup();
app.rebind("path.data").toConstantValue(dirSync().name);
Expand All @@ -62,14 +70,17 @@ export const makeApplication = async (configurationPath: string, options: Record
await app.resolve(CoreCryptoWif).register();
await app.resolve(CoreCryptoBlock).register();
await app.resolve(CoreEvmGasFee).register();
await app.resolve(CoreEvmConsensus).register();
await app.resolve(CoreCryptoTransaction).register();
await app.resolve(CoreCryptoTransactionEvmCall).register();
await app.resolve(CoreSnapshotLegacyImporter).register();
await app.resolve(EvmService).register();

// @ts-ignore
app.get<Contracts.Crypto.Configuration>(Identifiers.Cryptography.Configuration).setConfig({
milestones: [
{
evmSpec: Contracts.Evm.SpecId.SHANGHAI,
height: 0,
timeouts: {
blockPrepareTime: 4000,
Expand Down
36 changes: 34 additions & 2 deletions packages/configuration-generator/source/configuration-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,13 @@ export class ConfigurationGenerator {
};

const genesisWalletMnemonic = this.mnemonicGenerator.generate();
const validatorsMnemonics = this.mnemonicGenerator.generateMany(internalOptions.validators);
let validatorsMnemonics = this.mnemonicGenerator.generateMany(internalOptions.validators);

const tasks: Task[] = [
{
task: async () => {
if (!internalOptions.overwriteConfig && pathExistsSync(this.configurationPath)) {
throw new Error(`${this.configurationPath} already exists.`);
// throw new Error(`${this.configurationPath} already exists.`);
}

ensureDirSync(this.configurationPath);
Expand Down Expand Up @@ -139,6 +139,38 @@ export class ConfigurationGenerator {
network: {},
});

if (options.snapshot) {
const importer = this.app.get<Contracts.Snapshot.LegacyImporter>(
Identifiers.Snapshot.Legacy.Importer,
);
await importer.prepare(options.snapshot.path);

milestones[0].snapshot = { hash: importer.snapshotHash };

if (importer.validators) {
const importedValidatorMnemonics: string[] = [];
// create fake mnemonics for testing
const consensusKeyPairFactory = this.app.getTagged<Contracts.Crypto.KeyPairFactory>(
Identifiers.Cryptography.Identity.KeyPair.Factory,
"type",
"consensus",
);

for (const validator of importer.validators) {
const validatorMnemonic = this.mnemonicGenerator.generateDeterministic(
validator.username,
);
importedValidatorMnemonics.push(validatorMnemonic);

const consensusKeyPair = await consensusKeyPairFactory.fromMnemonic(validatorMnemonic);
validator.blsPublicKey = consensusKeyPair.publicKey;
}

// imported validators are already sorted by descending balance
validatorsMnemonics = importedValidatorMnemonics.slice(0, internalOptions.validators);
}
}

const genesisBlock = await this.genesisBlockGenerator.generate(
genesisWalletMnemonic,
validatorsMnemonics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ describe<{
{
reward: "0",
address: { bech32m: "ark" },
block: { version: 1, maxPayload: 2097152, maxTransactions: 150 },
block: { version: 1, maxGasLimit: 30_000_000, maxPayload: 2097152, maxTransactions: 150 },
blockTime: 8000,
height: 0,
evmSpec: Contracts.Evm.SpecId.SHANGHAI,
// @ts-ignore
gas: {
maximumGasLimit: 2000000,
Expand Down
Loading
Loading