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

fix: calculate and verify genesis block state hash #872

Merged
merged 8 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ describe<{
distribute: true,
epoch: new Date(),
premine: "2000000000",
}),
validators: 53,
} as Contracts.NetworkGenerator.InternalOptions),
);
});
});
73 changes: 49 additions & 24 deletions packages/configuration-generator/source/generators/genesis-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,12 @@ export class GenesisBlockGenerator extends Generator {
@tagged("instance", "evm")
private readonly evm!: Contracts.Evm.Instance;

@inject(EvmConsensusIdentifiers.Internal.Addresses.Deployer)
private readonly deployerAddress!: string;

#consensusProxyContractAddress!: string;

async generate(
genesisMnemonic: string,
validatorsMnemonics: string[],
options: Contracts.NetworkGenerator.GenesisBlockOptions,
options: Contracts.NetworkGenerator.InternalOptions,
): Promise<Contracts.Crypto.CommitData> {
const genesisWallet = await this.createWallet(genesisMnemonic);

Expand Down Expand Up @@ -96,13 +93,17 @@ export class GenesisBlockGenerator extends Generator {

async #prepareEvm(
genesisWalletAddress: string,
_validatorsCount: number,
options: Contracts.NetworkGenerator.GenesisBlockOptions,
validatorsCount: number,
options: Contracts.NetworkGenerator.InternalOptions,
) {
await this.app.resolve(Deployer).deploy({
generatorAddress: genesisWalletAddress,
timestamp: dayjs(options.epoch).valueOf(),
totalAmount: options.premine,
totalAmount: (options.distribute
? // Ensure no left over remains when distributing funds from the genesis address (see `#createTransferTransactions`)
BigNumber.make(options.premine).dividedBy(validatorsCount).times(validatorsCount)
: BigNumber.make(options.premine)
).toString(),
});

this.#consensusProxyContractAddress = this.app.get<string>(
Expand Down Expand Up @@ -201,7 +202,7 @@ export class GenesisBlockGenerator extends Generator {
async #createGenesisCommit(
premineKeys: Contracts.Crypto.KeyPair,
transactions: Contracts.Crypto.Transaction[],
options: Contracts.NetworkGenerator.GenesisBlockOptions,
options: Contracts.NetworkGenerator.InternalOptions,
): Promise<Contracts.Crypto.Commit> {
const genesisBlock = await this.#createGenesisBlock(premineKeys, transactions, options);

Expand All @@ -225,7 +226,7 @@ export class GenesisBlockGenerator extends Generator {
async #createGenesisBlock(
keys: Contracts.Crypto.KeyPair,
transactions: Contracts.Crypto.Transaction[],
options: Contracts.NetworkGenerator.GenesisBlockOptions,
options: Contracts.NetworkGenerator.InternalOptions,
): Promise<{ block: Contracts.Crypto.Block; transactions: Contracts.Crypto.TransactionData[] }> {
const totals: { amount: BigNumber; fee: BigNumber; gasUsed: number } = {
amount: BigNumber.ZERO,
Expand All @@ -234,11 +235,25 @@ export class GenesisBlockGenerator extends Generator {
};

const payloadBuffers: Buffer[] = [];
const commitKey = {
height: BigInt(0),
round: BigInt(0),
};
const timestamp = BigInt(dayjs(options.epoch).valueOf());
const generatorAddress = await this.app
.getTagged<Contracts.Crypto.AddressFactory>(
Identifiers.Cryptography.Identity.Address.Factory,
"type",
"wallet",
)
.fromPublicKey(keys.publicKey);

// The initial payload length takes the overhead for each serialized transaction into account
// which is a uint32 per transaction to store the individual length.
let payloadLength = transactions.length * 4;

await this.evm.prepareNextCommit({ commitKey });

const transactionData: Contracts.Crypto.TransactionData[] = [];
for (const transaction of transactions) {
const { serialized, data } = transaction;
Expand All @@ -247,13 +262,10 @@ export class GenesisBlockGenerator extends Generator {

const { receipt } = await this.evm.process({
blockContext: {
commitKey: {
height: BigInt(0),
round: BigInt(0),
},
commitKey,
gasLimit: BigInt(30_000_000),
timestamp: BigInt(dayjs(options.epoch).valueOf()),
validatorAddress: this.deployerAddress,
timestamp,
validatorAddress: generatorAddress,
},
caller: transaction.data.senderAddress,
data: Buffer.from(transaction.data.data, "hex"),
Expand All @@ -276,18 +288,28 @@ export class GenesisBlockGenerator extends Generator {
payloadLength += serialized.length;
}

await this.evm.updateRewardsAndVotes({
blockReward: 0n,
commitKey,
specId: Contracts.Evm.SpecId.SHANGHAI,
timestamp,
validatorAddress: generatorAddress,
});

await this.evm.calculateActiveValidators({
activeValidators: Utils.BigNumber.make(options.validators).toBigInt(),
commitKey,
specId: Contracts.Evm.SpecId.SHANGHAI,
timestamp,
validatorAddress: generatorAddress,
});

return {
block: await this.app.get<Contracts.Crypto.BlockFactory>(Identifiers.Cryptography.Block.Factory).make(
{
generatorAddress: await this.app
.getTagged<Contracts.Crypto.AddressFactory>(
Identifiers.Cryptography.Identity.Address.Factory,
"type",
"wallet",
)
.fromPublicKey(keys.publicKey),
generatorAddress,
height: 0,
logsBloom: "0".repeat(512),
logsBloom: await this.evm.logsBloom(commitKey),
numberOfTransactions: transactions.length,
payloadHash: (
await this.app
Expand All @@ -302,7 +324,10 @@ export class GenesisBlockGenerator extends Generator {
round: 0,
stateHash:
options.snapshot?.stateHash ??
"0000000000000000000000000000000000000000000000000000000000000000",
(await this.evm.stateHash(
commitKey,
"0000000000000000000000000000000000000000000000000000000000000000",
)),
timestamp: dayjs(options.epoch).valueOf(),
totalAmount: options.snapshot ? Utils.BigNumber.make(options.premine) : totals.amount,
totalFee: totals.fee,
Expand Down
1 change: 1 addition & 0 deletions packages/contracts/source/contracts/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface LegacyImporter {
validators: ImportedLegacyValidator[];
voters: ImportedLegacyVoter[];
snapshotHash: string;
result: LegacyImportResult | undefined;
}

export interface LegacyImportOptions {
Expand Down
Loading
Loading