From 8345d05dcf6e767a0c7f731f9dd7bbee25fadac5 Mon Sep 17 00:00:00 2001 From: Cayman Date: Wed, 17 Aug 2022 16:45:22 -0500 Subject: [PATCH] Consider state slot in getDomain --- .../signatureSets/aggregateAndProof.ts | 2 +- .../signatureSets/contributionAndProof.ts | 1 + .../validation/signatureSets/selectionProof.ts | 2 +- .../validation/signatureSets/syncCommittee.ts | 2 +- .../signatureSets/syncCommitteeContribution.ts | 2 +- .../syncCommitteeSelectionProof.ts | 2 +- .../utils/validationData/aggregateAndProof.ts | 4 ++-- .../test/utils/validationData/attestation.ts | 2 +- packages/config/README.md | 2 -- packages/config/src/genesisConfig/index.ts | 11 ++++++++--- packages/config/src/genesisConfig/types.ts | 7 ++++++- packages/flare/src/cmds/selfSlashAttester.ts | 2 +- packages/flare/src/cmds/selfSlashProposer.ts | 2 +- packages/light-client/src/validation.ts | 2 +- packages/light-client/test/utils/utils.ts | 2 +- .../src/block/processSyncCommittee.ts | 2 +- .../src/signatureSets/attesterSlashings.ts | 2 +- .../src/signatureSets/indexedAttestation.ts | 2 +- .../src/signatureSets/proposer.ts | 2 +- .../src/signatureSets/proposerSlashings.ts | 6 +++++- .../src/signatureSets/randao.ts | 2 +- .../src/signatureSets/voluntaryExits.ts | 2 +- .../validator/src/services/validatorStore.ts | 18 +++++++++--------- 23 files changed, 47 insertions(+), 34 deletions(-) diff --git a/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts b/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts index 85db76e36d3..043b2bd4cb0 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/aggregateAndProof.ts @@ -17,7 +17,7 @@ export function getAggregateAndProofSignatureSet( aggregateAndProof: phase0.SignedAggregateAndProof ): ISignatureSet { const slot = computeStartSlotAtEpoch(epoch); - const aggregatorDomain = state.config.getDomain(DOMAIN_AGGREGATE_AND_PROOF, slot); + const aggregatorDomain = state.config.getDomain(state.slot, DOMAIN_AGGREGATE_AND_PROOF, slot); const signingRoot = computeSigningRoot(ssz.phase0.AggregateAndProof, aggregateAndProof.message, aggregatorDomain); return { diff --git a/packages/beacon-node/src/chain/validation/signatureSets/contributionAndProof.ts b/packages/beacon-node/src/chain/validation/signatureSets/contributionAndProof.ts index 799978cb292..21e447b8367 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/contributionAndProof.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/contributionAndProof.ts @@ -13,6 +13,7 @@ export function getContributionAndProofSignatureSet( ): ISignatureSet { const {epochCtx} = state; const domain = state.config.getDomain( + state.slot, DOMAIN_CONTRIBUTION_AND_PROOF, signedContributionAndProof.message.contribution.slot ); diff --git a/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts b/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts index e68f5bea8d2..f82b5b80af5 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/selectionProof.ts @@ -14,7 +14,7 @@ export function getSelectionProofSignatureSet( aggregator: PublicKey, aggregateAndProof: phase0.SignedAggregateAndProof ): ISignatureSet { - const selectionProofDomain = state.config.getDomain(DOMAIN_SELECTION_PROOF, slot); + const selectionProofDomain = state.config.getDomain(state.slot, DOMAIN_SELECTION_PROOF, slot); return { type: SignatureSetType.single, diff --git a/packages/beacon-node/src/chain/validation/signatureSets/syncCommittee.ts b/packages/beacon-node/src/chain/validation/signatureSets/syncCommittee.ts index 25b80504483..ce2b2e2484a 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/syncCommittee.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/syncCommittee.ts @@ -11,7 +11,7 @@ export function getSyncCommitteeSignatureSet( state: CachedBeaconStateAllForks, syncCommittee: altair.SyncCommitteeMessage ): ISignatureSet { - const domain = state.config.getDomain(DOMAIN_SYNC_COMMITTEE, syncCommittee.slot); + const domain = state.config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE, syncCommittee.slot); return { type: SignatureSetType.single, diff --git a/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts b/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts index 8f854114d7b..71b7970716e 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeContribution.ts @@ -8,7 +8,7 @@ export function getSyncCommitteeContributionSignatureSet( contribution: altair.SyncCommitteeContribution, pubkeys: PublicKey[] ): ISignatureSet { - const domain = state.config.getDomain(DOMAIN_SYNC_COMMITTEE, contribution.slot); + const domain = state.config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE, contribution.slot); return { type: SignatureSetType.aggregate, pubkeys, diff --git a/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts b/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts index a180e43c9de..14fcfad2b92 100644 --- a/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts +++ b/packages/beacon-node/src/chain/validation/signatureSets/syncCommitteeSelectionProof.ts @@ -13,7 +13,7 @@ export function getSyncCommitteeSelectionProofSignatureSet( ): ISignatureSet { const {epochCtx, config} = state; const slot = contributionAndProof.contribution.slot; - const domain = config.getDomain(DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, slot); + const domain = config.getDomain(state.slot, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, slot); const signingData: altair.SyncAggregatorSelectionData = { slot, subcommitteeIndex: contributionAndProof.contribution.subcommitteeIndex, diff --git a/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts b/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts index 6b7d627d919..981933702db 100644 --- a/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts +++ b/packages/beacon-node/test/utils/validationData/aggregateAndProof.ts @@ -30,7 +30,7 @@ export function getAggregateAndProofValidData( (chain as {seenAggregators: IBeaconChain["seenAggregators"]}).seenAggregators = new SeenAggregators(); const aggregatorIndex = validatorIndex; - const proofDomain = state.config.getDomain(DOMAIN_SELECTION_PROOF, attSlot); + const proofDomain = state.config.getDomain(state.slot, DOMAIN_SELECTION_PROOF, attSlot); const proofSigningRoot = computeSigningRoot(ssz.Slot, attSlot, proofDomain); const aggregateAndProof: phase0.AggregateAndProof = { @@ -39,7 +39,7 @@ export function getAggregateAndProofValidData( selectionProof: signCached(sk, proofSigningRoot), }; - const aggDomain = state.config.getDomain(DOMAIN_AGGREGATE_AND_PROOF, attSlot); + const aggDomain = state.config.getDomain(state.slot, DOMAIN_AGGREGATE_AND_PROOF, attSlot); const aggSigningRoot = computeSigningRoot(ssz.phase0.AggregateAndProof, aggregateAndProof, aggDomain); const signedAggregateAndProof: phase0.SignedAggregateAndProof = { diff --git a/packages/beacon-node/test/utils/validationData/attestation.ts b/packages/beacon-node/test/utils/validationData/attestation.ts index cb8a99145bb..e11b5588e73 100644 --- a/packages/beacon-node/test/utils/validationData/attestation.ts +++ b/packages/beacon-node/test/utils/validationData/attestation.ts @@ -93,7 +93,7 @@ export function getAttestationValidData( }; const slot = computeStartSlotAtEpoch(attestationData.target.epoch); - const domain = state.config.getDomain(DOMAIN_BEACON_ATTESTER, slot); + const domain = state.config.getDomain(state.slot, DOMAIN_BEACON_ATTESTER, slot); const signingRoot = computeSigningRoot(ssz.phase0.AttestationData, attestationData, domain); const sk = getSecretKeyFromIndexCached(validatorIndex); diff --git a/packages/config/README.md b/packages/config/README.md index 91cf9ad45db..f99501c7841 100644 --- a/packages/config/README.md +++ b/packages/config/README.md @@ -112,8 +112,6 @@ import {config as chainConfig} from "@lodestar/config/default"; let genesisValidatorsRoot: Uint8Array = new Uint8Array(); const config: IBeaconConfig = createIBeaconConfig(chainConfig, genesisValidatorsRoot); - -const domain = config.getDomain(DOMAIN_DEPOSIT, GENESIS_SLOT); ``` ## License diff --git a/packages/config/src/genesisConfig/index.ts b/packages/config/src/genesisConfig/index.ts index 351d6ff957d..4504f0e90a4 100644 --- a/packages/config/src/genesisConfig/index.ts +++ b/packages/config/src/genesisConfig/index.ts @@ -1,4 +1,4 @@ -import {ForkName} from "@lodestar/params"; +import {ForkName, SLOTS_PER_EPOCH} from "@lodestar/params"; import {DomainType, ForkDigest, phase0, Root, Slot, ssz, Version} from "@lodestar/types"; import {toHexString} from "@chainsafe/ssz"; import {IChainForkConfig} from "../beaconConfig.js"; @@ -22,8 +22,13 @@ export function createICachedGenesis(chainForkConfig: IChainForkConfig, genesisV } return { - getDomain(domainType: DomainType, slot: Slot): Uint8Array { - const forkInfo = chainForkConfig.getForkInfo(slot); + getDomain(stateSlot: Slot, domainType: DomainType, messageSlot?: Slot): Uint8Array { + const stateForkInfo = chainForkConfig.getForkInfo(stateSlot); + const epoch = Math.floor(messageSlot ?? stateSlot / SLOTS_PER_EPOCH); + const forkInfo = + epoch < stateForkInfo.epoch + ? chainForkConfig.forksAscendingEpochOrder[Math.max(stateForkInfo.seq - 1, 0)] // previous + : stateForkInfo; // current let domainByType = domainCache.get(forkInfo.name); if (!domainByType) { domainByType = new Map(); diff --git a/packages/config/src/genesisConfig/types.ts b/packages/config/src/genesisConfig/types.ts index 614d86245e3..5a4745077d8 100644 --- a/packages/config/src/genesisConfig/types.ts +++ b/packages/config/src/genesisConfig/types.ts @@ -11,5 +11,10 @@ export interface IForkDigestContext { } export interface ICachedGenesis extends IForkDigestContext { - getDomain(domainType: DomainType, slot: Slot): Uint8Array; + /** + * Return the signature domain (fork version concatenated with domain type) of a message. + * + * Note: The configured fork schedule is always used rather than on-chain fork schedule. + */ + getDomain(stateSlot: Slot, domainType: DomainType, messageSlot?: Slot): Uint8Array; } diff --git a/packages/flare/src/cmds/selfSlashAttester.ts b/packages/flare/src/cmds/selfSlashAttester.ts index 562a5968166..edb9ff238b7 100644 --- a/packages/flare/src/cmds/selfSlashAttester.ts +++ b/packages/flare/src/cmds/selfSlashAttester.ts @@ -145,7 +145,7 @@ function signAttestationDataBigint( data: phase0.AttestationDataBigint ): Uint8Array { const slot = Number(data.slot as bigint); - const proposerDomain = config.getDomain(DOMAIN_BEACON_ATTESTER, slot); + const proposerDomain = config.getDomain(slot, DOMAIN_BEACON_ATTESTER); const signingRoot = computeSigningRoot(ssz.phase0.AttestationDataBigint, data, proposerDomain); const sigs = sks.map((sk) => sk.sign(signingRoot)); diff --git a/packages/flare/src/cmds/selfSlashProposer.ts b/packages/flare/src/cmds/selfSlashProposer.ts index 94ec12c577f..df8b2fd40e9 100644 --- a/packages/flare/src/cmds/selfSlashProposer.ts +++ b/packages/flare/src/cmds/selfSlashProposer.ts @@ -135,7 +135,7 @@ export async function selfSlashProposerHandler(args: SelfSlashArgs): Promise { - const domain = state.config.getDomain(DOMAIN_BEACON_PROPOSER, Number(signedHeader.message.slot as bigint)); + const domain = state.config.getDomain( + state.slot, + DOMAIN_BEACON_PROPOSER, + Number(signedHeader.message.slot as bigint) + ); return { type: SignatureSetType.single, diff --git a/packages/state-transition/src/signatureSets/randao.ts b/packages/state-transition/src/signatureSets/randao.ts index 5af17b4d9ea..4fc8b77e4e3 100644 --- a/packages/state-transition/src/signatureSets/randao.ts +++ b/packages/state-transition/src/signatureSets/randao.ts @@ -23,7 +23,7 @@ export function getRandaoRevealSignatureSet( const {epochCtx} = state; // should not get epoch from epochCtx const epoch = computeEpochAtSlot(block.slot); - const domain = state.config.getDomain(DOMAIN_RANDAO, block.slot); + const domain = state.config.getDomain(state.slot, DOMAIN_RANDAO, block.slot); return { type: SignatureSetType.single, diff --git a/packages/state-transition/src/signatureSets/voluntaryExits.ts b/packages/state-transition/src/signatureSets/voluntaryExits.ts index 9c766557588..b3c6e6f2847 100644 --- a/packages/state-transition/src/signatureSets/voluntaryExits.ts +++ b/packages/state-transition/src/signatureSets/voluntaryExits.ts @@ -25,7 +25,7 @@ export function getVoluntaryExitSignatureSet( ): ISignatureSet { const {epochCtx} = state; const slot = computeStartSlotAtEpoch(signedVoluntaryExit.message.epoch); - const domain = state.config.getDomain(DOMAIN_VOLUNTARY_EXIT, slot); + const domain = state.config.getDomain(state.slot, DOMAIN_VOLUNTARY_EXIT, slot); return { type: SignatureSetType.single, diff --git a/packages/validator/src/services/validatorStore.ts b/packages/validator/src/services/validatorStore.ts index 15873c9c61a..e91a37fbb9c 100644 --- a/packages/validator/src/services/validatorStore.ts +++ b/packages/validator/src/services/validatorStore.ts @@ -180,7 +180,7 @@ export class ValidatorStore { // Duties are filtered before-hard by doppelganger-safe, this assert should never throw this.assertDoppelgangerSafe(pubkey); - const proposerDomain = this.config.getDomain(DOMAIN_BEACON_PROPOSER, blindedOrFull.slot); + const proposerDomain = this.config.getDomain(currentSlot, DOMAIN_BEACON_PROPOSER, blindedOrFull.slot); const blockType = (blindedOrFull.body as bellatrix.BlindedBeaconBlockBody).executionPayloadHeader !== undefined ? ssz.bellatrix.BlindedBeaconBlock @@ -200,7 +200,7 @@ export class ValidatorStore { async signRandao(pubkey: BLSPubkey, slot: Slot): Promise { const epoch = computeEpochAtSlot(slot); - const randaoDomain = this.config.getDomain(DOMAIN_RANDAO, slot); + const randaoDomain = this.config.getDomain(slot, DOMAIN_RANDAO); const randaoSigningRoot = computeSigningRoot(ssz.Epoch, epoch, randaoDomain); return await this.getSignature(pubkey, randaoSigningRoot); @@ -223,7 +223,7 @@ export class ValidatorStore { this.validateAttestationDuty(duty, attestationData); const slot = computeStartSlotAtEpoch(attestationData.target.epoch); - const domain = this.config.getDomain(DOMAIN_BEACON_ATTESTER, slot); + const domain = this.config.getDomain(slot, DOMAIN_BEACON_ATTESTER); const signingRoot = computeSigningRoot(ssz.phase0.AttestationData, attestationData, domain); try { @@ -257,7 +257,7 @@ export class ValidatorStore { selectionProof, }; - const domain = this.config.getDomain(DOMAIN_AGGREGATE_AND_PROOF, aggregate.data.slot); + const domain = this.config.getDomain(duty.slot, DOMAIN_AGGREGATE_AND_PROOF); const signingRoot = computeSigningRoot(ssz.phase0.AggregateAndProof, aggregateAndProof, domain); return { @@ -272,7 +272,7 @@ export class ValidatorStore { slot: Slot, beaconBlockRoot: Root ): Promise { - const domain = this.config.getDomain(DOMAIN_SYNC_COMMITTEE, slot); + const domain = this.config.getDomain(slot, DOMAIN_SYNC_COMMITTEE); const signingRoot = computeSigningRoot(ssz.Root, beaconBlockRoot, domain); return { @@ -294,7 +294,7 @@ export class ValidatorStore { selectionProof, }; - const domain = this.config.getDomain(DOMAIN_CONTRIBUTION_AND_PROOF, contribution.slot); + const domain = this.config.getDomain(contribution.slot, DOMAIN_CONTRIBUTION_AND_PROOF); const signingRoot = computeSigningRoot(ssz.altair.ContributionAndProof, contributionAndProof, domain); return { @@ -304,7 +304,7 @@ export class ValidatorStore { } async signAttestationSelectionProof(pubkey: BLSPubkeyMaybeHex, slot: Slot): Promise { - const domain = this.config.getDomain(DOMAIN_SELECTION_PROOF, slot); + const domain = this.config.getDomain(slot, DOMAIN_SELECTION_PROOF); const signingRoot = computeSigningRoot(ssz.Slot, slot, domain); return await this.getSignature(pubkey, signingRoot); @@ -315,7 +315,7 @@ export class ValidatorStore { slot: Slot, subcommitteeIndex: number ): Promise { - const domain = this.config.getDomain(DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF, slot); + const domain = this.config.getDomain(slot, DOMAIN_SYNC_COMMITTEE_SELECTION_PROOF); const signingData: altair.SyncAggregatorSelectionData = { slot, subcommitteeIndex, @@ -331,7 +331,7 @@ export class ValidatorStore { validatorIndex: number, exitEpoch: Epoch ): Promise { - const domain = this.config.getDomain(DOMAIN_VOLUNTARY_EXIT, computeStartSlotAtEpoch(exitEpoch)); + const domain = this.config.getDomain(computeStartSlotAtEpoch(exitEpoch), DOMAIN_VOLUNTARY_EXIT); const voluntaryExit: phase0.VoluntaryExit = {epoch: exitEpoch, validatorIndex}; const signingRoot = computeSigningRoot(ssz.phase0.VoluntaryExit, voluntaryExit, domain);