From 218c05df9a80430630a5fcc2c0a181cedf2ab9b2 Mon Sep 17 00:00:00 2001 From: fearlessfe <505380967@qq.com> Date: Wed, 11 Sep 2024 08:20:15 +0800 Subject: [PATCH 1/2] feat: add history proof validation test --- portalnetwork/beacon/beacon_network.go | 29 ++++++++++------ portalnetwork/beacon/beacon_network_test.go | 25 +++++++++++++- portalnetwork/beacon/test_utils.go | 37 +++++++++++---------- 3 files changed, 61 insertions(+), 30 deletions(-) diff --git a/portalnetwork/beacon/beacon_network.go b/portalnetwork/beacon/beacon_network.go index 874cba9a6430..5ef5f64ea5d4 100644 --- a/portalnetwork/beacon/beacon_network.go +++ b/portalnetwork/beacon/beacon_network.go @@ -253,20 +253,10 @@ func (bn *BeaconNetwork) validateContent(contentKey []byte, content []byte) erro return nil // TODO: VERIFY case HistoricalSummaries: - key := &HistoricalSummariesWithProofKey{} - err := key.Deserialize(codec.NewDecodingReader(bytes.NewReader(contentKey[1:]), uint64(len(contentKey[1:])))) - if err != nil { - return err - } - forkedHistoricalSummariesWithProof := &ForkedHistoricalSummariesWithProof{} - err = forkedHistoricalSummariesWithProof.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(content), uint64(len(content)))) + forkedHistoricalSummariesWithProof, err := bn.generalSummariesValidation(contentKey, content) if err != nil { return err } - if forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH != common.Epoch(key.Epoch) { - return fmt.Errorf("historical summaries with proof epoch does not match the content key epoch: %d != %d", forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH, key.Epoch) - } - // TODO get root from light client header := bn.lightClient.GetFinalityHeader() latestFinalizedRoot := header.StateRoot @@ -329,6 +319,23 @@ func (bn *BeaconNetwork) processContentLoop(ctx context.Context) { } } +func (bn *BeaconNetwork) generalSummariesValidation(contentKey, content []byte) (*ForkedHistoricalSummariesWithProof, error) { + key := &HistoricalSummariesWithProofKey{} + err := key.Deserialize(codec.NewDecodingReader(bytes.NewReader(contentKey[1:]), uint64(len(contentKey[1:])))) + if err != nil { + return nil, err + } + forkedHistoricalSummariesWithProof := &ForkedHistoricalSummariesWithProof{} + err = forkedHistoricalSummariesWithProof.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(content), uint64(len(content)))) + if err != nil { + return nil, err + } + if forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH != common.Epoch(key.Epoch) { + return nil, fmt.Errorf("historical summaries with proof epoch does not match the content key epoch: %d != %d", forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH, key.Epoch) + } + return forkedHistoricalSummariesWithProof, nil +} + func (bn *BeaconNetwork) stateSummariesValidation(f ForkedHistoricalSummariesWithProof, latestFinalizedRoot common.Root) bool { proof := f.HistoricalSummariesWithProof.Proof summariesRoot := f.HistoricalSummariesWithProof.HistoricalSummaries.HashTreeRoot(bn.spec, tree.GetHashFn()) diff --git a/portalnetwork/beacon/beacon_network_test.go b/portalnetwork/beacon/beacon_network_test.go index 72c17d627f76..9acd391535f5 100644 --- a/portalnetwork/beacon/beacon_network_test.go +++ b/portalnetwork/beacon/beacon_network_test.go @@ -82,6 +82,29 @@ func TestLightClientOptimisticUpdateValidation(t *testing.T) { } func TestHistorySummariesWithProofValidation(t *testing.T) { - _, err := GetHistorySummariesWithProof() + historySummariesWithProof, root, err := GetHistorySummariesWithProof() require.NoError(t, err) + + key := &HistoricalSummariesWithProofKey{ + Epoch: 450508969718611630, + } + var keyBuf bytes.Buffer + err = key.Serialize(codec.NewEncodingWriter(&keyBuf)) + require.NoError(t, err) + contentKey := make([]byte, 0) + contentKey = append(contentKey, byte(HistoricalSummaries)) + contentKey = append(contentKey, keyBuf.Bytes()...) + + bn := NewBeaconNetwork(nil) + var buf bytes.Buffer + err = historySummariesWithProof.Serialize(bn.spec, codec.NewEncodingWriter(&buf)) + require.NoError(t, err) + content := make([]byte, 0) + content = append(content, Deneb[:]...) + content = append(content, buf.Bytes()...) + + forkedHistorySummaries, err := bn.generalSummariesValidation(contentKey, content) + require.NoError(t, err) + valid := bn.stateSummariesValidation(*forkedHistorySummaries, root) + require.True(t, valid) } diff --git a/portalnetwork/beacon/test_utils.go b/portalnetwork/beacon/test_utils.go index 5ee027cd052b..fcc3530d45b7 100644 --- a/portalnetwork/beacon/test_utils.go +++ b/portalnetwork/beacon/test_utils.go @@ -158,24 +158,25 @@ func GetLightClientOptimisticUpdate(number uint8) (ForkedLightClientOptimisticUp return *bootstrap, nil } -func GetHistorySummariesWithProof() (HistoricalSummariesWithProof, error) { +func GetHistorySummariesWithProof() (HistoricalSummariesWithProof, common.Root, error) { file, err := os.ReadFile("testdata/beacon/BeaconState/ssz_random/case_0/serialized.ssz_snappy") if err != nil { - return HistoricalSummariesWithProof{}, err + return HistoricalSummariesWithProof{}, common.Root{}, err } data, err := snappy.Decode(nil, file) if err != nil { - return HistoricalSummariesWithProof{}, err + return HistoricalSummariesWithProof{}, common.Root{},err } beaconState := &deneb.BeaconState{} err = beaconState.Deserialize(configs.Mainnet, codec.NewDecodingReader(bytes.NewReader(data), uint64(len(data)))) if err != nil { - return HistoricalSummariesWithProof{}, err + return HistoricalSummariesWithProof{}, common.Root{},err } + root := beaconState.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) proof, err := BuildHistoricalSummariesProof(*beaconState) if err != nil { - return HistoricalSummariesWithProof{}, err + return HistoricalSummariesWithProof{}, common.Root{},err } summariesProof := [5]common.Bytes32{tree.Root(proof[0]), tree.Root(proof[1]), tree.Root(proof[2]), tree.Root(proof[3]), tree.Root(proof[4])} return HistoricalSummariesWithProof{ @@ -184,7 +185,7 @@ func GetHistorySummariesWithProof() (HistoricalSummariesWithProof, error) { Proof: HistoricalSummariesProof{ Proof: summariesProof, }, - }, nil + }, root, nil } func BuildHistoricalSummariesProof(beaconState deneb.BeaconState) ([][]byte, error) { @@ -205,18 +206,18 @@ func BuildHistoricalSummariesProof(beaconState deneb.BeaconState) ([][]byte, err leaves[13] = beaconState.RandaoMixes.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) leaves[14] = beaconState.Slashings.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) leaves[15] = beaconState.PreviousEpochParticipation.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) - leaves[16] = beaconState.JustificationBits.HashTreeRoot(tree.GetHashFn()) - leaves[17] = beaconState.PreviousEpochParticipation.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) - leaves[18] = beaconState.CurrentJustifiedCheckpoint.HashTreeRoot(tree.GetHashFn()) - leaves[19] = beaconState.FinalizedCheckpoint.HashTreeRoot(tree.GetHashFn()) - leaves[20] = beaconState.InactivityScores.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) - leaves[21] = beaconState.CurrentSyncCommittee.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) - leaves[22] = beaconState.NextSyncCommittee.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) - leaves[23] = beaconState.LatestExecutionPayloadHeader.HashTreeRoot(tree.GetHashFn()) - leaves[24] = beaconState.NextWithdrawalIndex.HashTreeRoot(tree.GetHashFn()) - leaves[25] = beaconState.NextWithdrawalValidatorIndex.HashTreeRoot(tree.GetHashFn()) - leaves[26] = beaconState.HistoricalSummaries.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) - leaves[27] = tree.Root{} + leaves[16] = beaconState.CurrentEpochParticipation.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) + leaves[17] = beaconState.JustificationBits.HashTreeRoot(tree.GetHashFn()) + leaves[18] = beaconState.PreviousJustifiedCheckpoint.HashTreeRoot(tree.GetHashFn()) + leaves[19] = beaconState.CurrentJustifiedCheckpoint.HashTreeRoot(tree.GetHashFn()) + leaves[20] = beaconState.FinalizedCheckpoint.HashTreeRoot(tree.GetHashFn()) + leaves[21] = beaconState.InactivityScores.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) + leaves[22] = beaconState.CurrentSyncCommittee.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) + leaves[23] = beaconState.NextSyncCommittee.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) + leaves[24] = beaconState.LatestExecutionPayloadHeader.HashTreeRoot(tree.GetHashFn()) + leaves[25] = beaconState.NextWithdrawalIndex.HashTreeRoot(tree.GetHashFn()) + leaves[26] = beaconState.NextWithdrawalValidatorIndex.HashTreeRoot(tree.GetHashFn()) + leaves[27] = beaconState.HistoricalSummaries.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) leaves[28] = tree.Root{} leaves[29] = tree.Root{} leaves[30] = tree.Root{} From d9a379d3fa4a8e5fbde67e9bc447a80e5c24a1f5 Mon Sep 17 00:00:00 2001 From: fearlseefe <505380967@qq.com> Date: Wed, 11 Sep 2024 16:36:29 +0800 Subject: [PATCH 2/2] fix: lint error --- portalnetwork/beacon/beacon_network.go | 26 +++++++++++++------------- portalnetwork/beacon/test_utils.go | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/portalnetwork/beacon/beacon_network.go b/portalnetwork/beacon/beacon_network.go index 5ef5f64ea5d4..e5518d98ebff 100644 --- a/portalnetwork/beacon/beacon_network.go +++ b/portalnetwork/beacon/beacon_network.go @@ -321,19 +321,19 @@ func (bn *BeaconNetwork) processContentLoop(ctx context.Context) { func (bn *BeaconNetwork) generalSummariesValidation(contentKey, content []byte) (*ForkedHistoricalSummariesWithProof, error) { key := &HistoricalSummariesWithProofKey{} - err := key.Deserialize(codec.NewDecodingReader(bytes.NewReader(contentKey[1:]), uint64(len(contentKey[1:])))) - if err != nil { - return nil, err - } - forkedHistoricalSummariesWithProof := &ForkedHistoricalSummariesWithProof{} - err = forkedHistoricalSummariesWithProof.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(content), uint64(len(content)))) - if err != nil { - return nil, err - } - if forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH != common.Epoch(key.Epoch) { - return nil, fmt.Errorf("historical summaries with proof epoch does not match the content key epoch: %d != %d", forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH, key.Epoch) - } - return forkedHistoricalSummariesWithProof, nil + err := key.Deserialize(codec.NewDecodingReader(bytes.NewReader(contentKey[1:]), uint64(len(contentKey[1:])))) + if err != nil { + return nil, err + } + forkedHistoricalSummariesWithProof := &ForkedHistoricalSummariesWithProof{} + err = forkedHistoricalSummariesWithProof.Deserialize(bn.spec, codec.NewDecodingReader(bytes.NewReader(content), uint64(len(content)))) + if err != nil { + return nil, err + } + if forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH != common.Epoch(key.Epoch) { + return nil, fmt.Errorf("historical summaries with proof epoch does not match the content key epoch: %d != %d", forkedHistoricalSummariesWithProof.HistoricalSummariesWithProof.EPOCH, key.Epoch) + } + return forkedHistoricalSummariesWithProof, nil } func (bn *BeaconNetwork) stateSummariesValidation(f ForkedHistoricalSummariesWithProof, latestFinalizedRoot common.Root) bool { diff --git a/portalnetwork/beacon/test_utils.go b/portalnetwork/beacon/test_utils.go index fcc3530d45b7..9f0550e54871 100644 --- a/portalnetwork/beacon/test_utils.go +++ b/portalnetwork/beacon/test_utils.go @@ -165,18 +165,18 @@ func GetHistorySummariesWithProof() (HistoricalSummariesWithProof, common.Root, } data, err := snappy.Decode(nil, file) if err != nil { - return HistoricalSummariesWithProof{}, common.Root{},err + return HistoricalSummariesWithProof{}, common.Root{}, err } beaconState := &deneb.BeaconState{} err = beaconState.Deserialize(configs.Mainnet, codec.NewDecodingReader(bytes.NewReader(data), uint64(len(data)))) if err != nil { - return HistoricalSummariesWithProof{}, common.Root{},err + return HistoricalSummariesWithProof{}, common.Root{}, err } root := beaconState.HashTreeRoot(configs.Mainnet, tree.GetHashFn()) proof, err := BuildHistoricalSummariesProof(*beaconState) if err != nil { - return HistoricalSummariesWithProof{}, common.Root{},err + return HistoricalSummariesWithProof{}, common.Root{}, err } summariesProof := [5]common.Bytes32{tree.Root(proof[0]), tree.Root(proof[1]), tree.Root(proof[2]), tree.Root(proof[3]), tree.Root(proof[4])} return HistoricalSummariesWithProof{