Skip to content

Commit 65869da

Browse files
authored
Added warning for genesis state not matching latest block header (#9482)
This will give earlier warning when an invalid genesis state is in use. Signed-off-by: Paul Harris <paul.harris@consensys.net>
1 parent 1376bc9 commit 65869da

7 files changed

Lines changed: 59 additions & 20 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@
2020
- Improved configuration loading to use builtin configurations to default any fields we need that were missing from a passed in configuration.
2121
- Add `/teku/v1/admin/add_peer` endpoint to allow adding static peers via the REST API.
2222

23-
### Bug Fixes
23+
### Bug Fixes
24+
- Added an error if the genesis state has invalid data in its latest block header.

ethereum/spec/src/main/java/tech/pegasys/teku/spec/datastructures/state/AnchorPoint.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ public static AnchorPoint fromGenesisState(final Spec spec, final BeaconState ge
8484
SignedBeaconBlock.create(spec, genesisBlock, BLSSignature.empty());
8585

8686
final Bytes32 genesisBlockRoot = genesisBlock.hashTreeRoot();
87+
checkArgument(
88+
genesisState.getLatestBlockHeader().getBodyRoot().equals(genesisBlock.getBodyRoot()),
89+
String.format(
90+
"Genesis block root %s does not match genesis state latest block root %s",
91+
genesisState.getLatestBlockHeader().getBodyRoot(), genesisBlock.getBodyRoot()));
8792
final UInt64 genesisEpoch = spec.getCurrentEpoch(genesisState);
8893
final Checkpoint genesisCheckpoint = new Checkpoint(genesisEpoch, genesisBlockRoot);
8994

ethereum/spec/src/test/java/tech/pegasys/teku/spec/datastructures/state/AnchorPointTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import tech.pegasys.teku.spec.Spec;
2222
import tech.pegasys.teku.spec.TestSpecFactory;
2323
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockAndState;
24+
import tech.pegasys.teku.spec.datastructures.state.beaconstate.BeaconState;
2425
import tech.pegasys.teku.spec.util.DataStructureUtil;
2526

2627
public class AnchorPointTest {
@@ -41,4 +42,15 @@ public void create_withCheckpointPriorToState() {
4142
.isInstanceOf(IllegalArgumentException.class)
4243
.hasMessageContaining("Block must be at or prior to the start of the checkpoint epoch");
4344
}
45+
46+
@Test
47+
public void shouldDetectInvalidGenesisStateWithMismatchedBlockHeader() {
48+
final BeaconState beaconState = dataStructureUtil.genesisBeaconState(12);
49+
final BeaconState brokenGenesisState =
50+
beaconState.updated(
51+
s -> s.setLatestBlockHeader(dataStructureUtil.randomBeaconBlockHeader()));
52+
assertThatThrownBy(() -> AnchorPoint.fromGenesisState(spec, brokenGenesisState))
53+
.isInstanceOf(IllegalArgumentException.class)
54+
.hasMessageContaining("does not match genesis state latest block root");
55+
}
4456
}

ethereum/spec/src/testFixtures/java/tech/pegasys/teku/spec/util/DataStructureUtil.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import tech.pegasys.teku.infrastructure.ssz.schema.collections.SszPrimitiveListSchema;
7878
import tech.pegasys.teku.infrastructure.ssz.schema.collections.SszPrimitiveVectorSchema;
7979
import tech.pegasys.teku.infrastructure.ssz.schema.collections.SszUInt64ListSchema;
80+
import tech.pegasys.teku.infrastructure.time.SystemTimeProvider;
8081
import tech.pegasys.teku.infrastructure.unsigned.UInt64;
8182
import tech.pegasys.teku.kzg.KZGCell;
8283
import tech.pegasys.teku.kzg.KZGCommitment;
@@ -144,6 +145,7 @@
144145
import tech.pegasys.teku.spec.datastructures.execution.versions.electra.ExecutionRequestsSchema;
145146
import tech.pegasys.teku.spec.datastructures.execution.versions.electra.WithdrawalRequest;
146147
import tech.pegasys.teku.spec.datastructures.forkchoice.VoteTracker;
148+
import tech.pegasys.teku.spec.datastructures.interop.MockStartDepositGenerator;
147149
import tech.pegasys.teku.spec.datastructures.lightclient.LightClientBootstrap;
148150
import tech.pegasys.teku.spec.datastructures.lightclient.LightClientBootstrapSchema;
149151
import tech.pegasys.teku.spec.datastructures.lightclient.LightClientHeaderSchema;
@@ -198,6 +200,7 @@
198200
import tech.pegasys.teku.spec.datastructures.type.SszKZGProof;
199201
import tech.pegasys.teku.spec.datastructures.type.SszPublicKey;
200202
import tech.pegasys.teku.spec.datastructures.type.SszSignature;
203+
import tech.pegasys.teku.spec.datastructures.util.DepositGenerator;
201204
import tech.pegasys.teku.spec.datastructures.validator.BeaconPreparableProposer;
202205
import tech.pegasys.teku.spec.executionlayer.ForkChoiceState;
203206
import tech.pegasys.teku.spec.executionlayer.PayloadBuildingAttributes;
@@ -1915,6 +1918,22 @@ public ForkChoiceState randomForkChoiceState(
19151918
optimisticHead);
19161919
}
19171920

1921+
public BeaconState genesisBeaconState(final int validatorCount) {
1922+
final List<BLSKeyPair> keyPairs = new ArrayList<>();
1923+
for (int i = 0; i < validatorCount; i++) {
1924+
keyPairs.add(randomKeyPair());
1925+
}
1926+
final List<DepositData> initialDepositData =
1927+
new MockStartDepositGenerator(spec, new DepositGenerator(spec, true))
1928+
.createDeposits(keyPairs, spec.getGenesisSpecConfig().getMaxEffectiveBalance());
1929+
1930+
final List<Deposit> deposits = initialDepositData.stream().map(Deposit::new).toList();
1931+
final BeaconState initialState =
1932+
spec.initializeBeaconStateFromEth1(Bytes32.ZERO, UInt64.ZERO, deposits, Optional.empty());
1933+
return initialState.updated(
1934+
state -> state.setGenesisTime(new SystemTimeProvider().getTimeInSeconds()));
1935+
}
1936+
19181937
public BeaconState randomBeaconState() {
19191938
return randomBeaconState(100, 100);
19201939
}
@@ -1999,6 +2018,9 @@ public BeaconStateBuilderElectra stateBuilderElectra(
19992018
}
20002019

20012020
public BeaconState randomBeaconState(final UInt64 slot) {
2021+
if (slot.isZero()) {
2022+
return genesisBeaconState(100);
2023+
}
20022024
return randomBeaconState().updated(state -> state.setSlot(slot));
20032025
}
20042026

ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/validation/AbstractAttestationValidatorTest.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,13 @@
1515

1616
import static tech.pegasys.teku.infrastructure.async.SafeFutureAssert.safeJoin;
1717

18-
import java.util.List;
1918
import java.util.concurrent.CompletableFuture;
2019
import java.util.function.Predicate;
2120
import org.apache.logging.log4j.LogManager;
2221
import org.apache.logging.log4j.Logger;
2322
import org.junit.jupiter.api.AfterAll;
2423
import org.junit.jupiter.api.BeforeAll;
2524
import org.junit.jupiter.api.BeforeEach;
26-
import tech.pegasys.teku.bls.BLSKeyGenerator;
27-
import tech.pegasys.teku.bls.BLSKeyPair;
2825
import tech.pegasys.teku.bls.BLSSignatureVerifier;
2926
import tech.pegasys.teku.infrastructure.metrics.StubMetricsSystem;
3027
import tech.pegasys.teku.spec.Spec;
@@ -76,17 +73,18 @@
7673
abstract class AbstractAttestationValidatorTest {
7774
private static final Logger LOG = LogManager.getLogger();
7875

79-
private static final List<BLSKeyPair> VALIDATOR_KEYS = BLSKeyGenerator.generateKeyPairs(64);
80-
8176
protected final Spec spec = createSpec();
8277
protected final AttestationSchema<?> attestationSchema =
8378
spec.getGenesisSchemaDefinitions().getAttestationSchema();
8479
protected final StorageSystem storageSystem =
85-
InMemoryStorageSystemBuilder.buildDefault(StateStorageMode.ARCHIVE);
80+
InMemoryStorageSystemBuilder.create()
81+
.numberOfValidators(64)
82+
.specProvider(spec)
83+
.storageMode(StateStorageMode.ARCHIVE)
84+
.build();
8685
protected final RecentChainData recentChainData = storageSystem.recentChainData();
87-
protected final ChainBuilder chainBuilder = ChainBuilder.create(spec, VALIDATOR_KEYS);
88-
protected final ChainUpdater chainUpdater =
89-
new ChainUpdater(storageSystem.recentChainData(), chainBuilder);
86+
protected final ChainBuilder chainBuilder = storageSystem.chainBuilder();
87+
protected final ChainUpdater chainUpdater = storageSystem.chainUpdater();
9088
protected final AttestationGenerator attestationGenerator =
9189
new AttestationGenerator(spec, chainBuilder.getValidatorKeys());
9290
protected final AsyncBLSSignatureVerifier signatureVerifier =
@@ -108,7 +106,7 @@ public static void reset() {
108106

109107
@BeforeEach
110108
public void setUp() {
111-
chainUpdater.initializeGenesis(false);
109+
storageSystem.chainUpdater().initializeGenesis(false);
112110
}
113111

114112
public abstract Spec createSpec();

ethereum/statetransition/src/test/java/tech/pegasys/teku/statetransition/validation/AggregateAttestationValidatorTest.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import org.junit.jupiter.api.BeforeAll;
3737
import org.junit.jupiter.api.BeforeEach;
3838
import org.junit.jupiter.api.TestTemplate;
39-
import tech.pegasys.teku.bls.BLSKeyPair;
4039
import tech.pegasys.teku.bls.BLSSignature;
4140
import tech.pegasys.teku.bls.BLSSignatureVerifier;
4241
import tech.pegasys.teku.infrastructure.async.SafeFuture;
@@ -51,7 +50,6 @@
5150
import tech.pegasys.teku.spec.datastructures.blocks.BeaconBlockAndState;
5251
import tech.pegasys.teku.spec.datastructures.blocks.SignedBlockAndState;
5352
import tech.pegasys.teku.spec.datastructures.blocks.StateAndBlockSummary;
54-
import tech.pegasys.teku.spec.datastructures.interop.MockStartValidatorKeyPairFactory;
5553
import tech.pegasys.teku.spec.datastructures.operations.AggregateAndProof;
5654
import tech.pegasys.teku.spec.datastructures.operations.AggregateAndProof.AggregateAndProofSchema;
5755
import tech.pegasys.teku.spec.datastructures.operations.Attestation;
@@ -119,8 +117,6 @@
119117
@TestSpecContext(milestone = {PHASE0, ELECTRA})
120118
class AggregateAttestationValidatorTest {
121119

122-
private static final List<BLSKeyPair> VALIDATOR_KEYS =
123-
new MockStartValidatorKeyPairFactory().generateKeyPairs(0, 1024);
124120
private Spec spec;
125121
private SpecVersion genesisSpec;
126122
private DataStructureUtil dataStructureUtil;
@@ -154,10 +150,15 @@ public void setUp(final SpecContext specContext) {
154150
signedAggregateAndProofSchema =
155151
specContext.getSchemaDefinitions().getSignedAggregateAndProofSchema();
156152
aggregateAndProofSchema = specContext.getSchemaDefinitions().getAggregateAndProofSchema();
157-
storageSystem = InMemoryStorageSystemBuilder.buildDefault(StateStorageMode.ARCHIVE);
158-
159-
final ChainBuilder chainBuilder = ChainBuilder.create(spec, VALIDATOR_KEYS);
160-
chainUpdater = new ChainUpdater(storageSystem.recentChainData(), chainBuilder);
153+
storageSystem =
154+
InMemoryStorageSystemBuilder.create()
155+
.specProvider(spec)
156+
.numberOfValidators(1024)
157+
.storageMode(StateStorageMode.ARCHIVE)
158+
.build();
159+
160+
final ChainBuilder chainBuilder = storageSystem.chainBuilder();
161+
chainUpdater = storageSystem.chainUpdater();
161162
generator = new AggregateGenerator(spec, chainBuilder.getValidatorKeys());
162163

163164
attestationValidator = mock(AttestationValidator.class);

storage/src/testFixtures/java/tech/pegasys/teku/storage/client/ChainUpdater.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ public SignedBlockAndState initializeGenesisWithPayload(
117117
return initializeGenesis(signDeposits, Optional.of(executionPayloadHeader));
118118
}
119119

120-
public SignedBlockAndState initializeGenesis(
120+
private SignedBlockAndState initializeGenesis(
121121
final boolean signDeposits, final Optional<ExecutionPayloadHeader> payloadHeader) {
122122
final SignedBlockAndState genesis =
123123
chainBuilder.generateGenesis(UInt64.ZERO, signDeposits, payloadHeader);

0 commit comments

Comments
 (0)