From 2d1e1f844a665c876f736a4d542d107180aae9a5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 Aug 2025 17:55:34 +0000 Subject: [PATCH 1/4] Initial plan From a1e2e2c6b3a9cff01a51e94c41dfb44bebec8957 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 Aug 2025 18:10:37 +0000 Subject: [PATCH 2/4] fix: change proof functions to return values instead of pointers - Change ProofsFromByteSlices to return []Proof instead of []*Proof - Change ProofFromProto to return Proof instead of *Proof - Change ProofsFromLeafHashes to return []Proof instead of []*Proof - Update all call sites to remove pointer dereferences - Convert RowProof.Proofs field to []merkle.Proof for consistency - Update helper functions to provide pointers where needed for external APIs Co-authored-by: tzdybal <1138893+tzdybal@users.noreply.github.com> --- consensus/propagation/types/types.go | 10 +++++++--- crypto/merkle/proof.go | 30 ++++++++++++++-------------- crypto/merkle/proof_test.go | 6 +++--- crypto/merkle/proof_value.go | 2 +- rpc/core/blocks.go | 2 +- types/part_set.go | 10 +++++----- types/results.go | 2 +- types/row_proof.go | 6 +++--- types/row_proof_test.go | 4 ++-- types/tx.go | 4 ++-- 10 files changed, 40 insertions(+), 36 deletions(-) diff --git a/consensus/propagation/types/types.go b/consensus/propagation/types/types.go index ad44fea294..36f884f259 100644 --- a/consensus/propagation/types/types.go +++ b/consensus/propagation/types/types.go @@ -209,14 +209,18 @@ func (c *CompactBlock) Proofs() ([]*merkle.Proof, error) { c.proofsCache = make([]*merkle.Proof, 0, len(c.PartsHashes)) root, proofs := merkle.ProofsFromLeafHashes(c.PartsHashes[:total]) - c.proofsCache = append(c.proofsCache, proofs...) + for i := range proofs { + c.proofsCache = append(c.proofsCache, &proofs[i]) + } if !bytes.Equal(root, c.Proposal.BlockID.PartSetHeader.Hash) { return c.proofsCache, fmt.Errorf("incorrect PartsHash: original root") } parityRoot, eproofs := merkle.ProofsFromLeafHashes(c.PartsHashes[total:]) - c.proofsCache = append(c.proofsCache, eproofs...) + for i := range eproofs { + c.proofsCache = append(c.proofsCache, &eproofs[i]) + } if !bytes.Equal(c.BpHash, parityRoot) { return c.proofsCache, fmt.Errorf("incorrect PartsHash: parity root") @@ -483,7 +487,7 @@ func RecoveryPartFromProto(r *protoprop.RecoveryPart) (*RecoveryPart, error) { Round: r.Round, Index: r.Index, Data: r.Data, - Proof: proof, + Proof: &proof, } return rp, rp.ValidateBasic() } diff --git a/crypto/merkle/proof.go b/crypto/merkle/proof.go index 8c014268d7..43ee331863 100644 --- a/crypto/merkle/proof.go +++ b/crypto/merkle/proof.go @@ -32,12 +32,12 @@ type Proof struct { // ProofsFromByteSlices computes inclusion proof for given items. // proofs[0] is the proof for items[0]. -func ProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []*Proof) { +func ProofsFromByteSlices(items [][]byte) (rootHash []byte, proofs []Proof) { trails, rootSPN := trailsFromByteSlices(items) rootHash = rootSPN.Hash - proofs = make([]*Proof, len(items)) + proofs = make([]Proof, len(items)) for i, trail := range trails { - proofs[i] = &Proof{ + proofs[i] = Proof{ Total: int64(len(items)), Index: int64(i), LeafHash: trail.Hash, @@ -145,20 +145,20 @@ func (sp *Proof) ToProto() *cmtcrypto.Proof { return pb } -func ProofFromProto(pb *cmtcrypto.Proof, optional bool) (*Proof, error) { +func ProofFromProto(pb *cmtcrypto.Proof, optional bool) (Proof, error) { if pb == nil || (len(pb.LeafHash) == 0 && len(pb.Aunts) == 0) { if optional { - return nil, nil + return Proof{}, nil } - return nil, errors.New("nil proof") + return Proof{}, errors.New("nil proof") } - sp := new(Proof) - - sp.Total = pb.Total - sp.Index = pb.Index - sp.LeafHash = pb.LeafHash - sp.Aunts = pb.Aunts + sp := Proof{ + Total: pb.Total, + Index: pb.Index, + LeafHash: pb.LeafHash, + Aunts: pb.Aunts, + } return sp, sp.ValidateBasic() } @@ -275,12 +275,12 @@ func trailsFromLeafHashes(leafHashes [][]byte) (trails []*ProofNode, root *Proof } } -func ProofsFromLeafHashes(leafHashes [][]byte) (rootHash []byte, proofs []*Proof) { +func ProofsFromLeafHashes(leafHashes [][]byte) (rootHash []byte, proofs []Proof) { trails, rootNode := trailsFromLeafHashes(leafHashes) rootHash = rootNode.Hash - proofs = make([]*Proof, len(leafHashes)) + proofs = make([]Proof, len(leafHashes)) for i, trail := range trails { - proofs[i] = &Proof{ + proofs[i] = Proof{ Total: int64(len(leafHashes)), Index: int64(i), LeafHash: trail.Hash, diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go index 5d940ae103..00a7006dd7 100644 --- a/crypto/merkle/proof_test.go +++ b/crypto/merkle/proof_test.go @@ -164,7 +164,7 @@ func TestProofValidateBasic(t *testing.T) { []byte("watermelon"), []byte("kiwi"), }) - tc.malleateProof(proofs[0]) + tc.malleateProof(&proofs[0]) err := proofs[0].ValidateBasic() if tc.errStr != "" { assert.Contains(t, err.Error(), tc.errStr) @@ -186,7 +186,7 @@ func TestVoteProtobuf(t *testing.T) { }{ {"empty proof", &Proof{}, false}, {"failure nil", nil, false}, - {"success", proofs[0], true}, + {"success", &proofs[0], true}, } for _, tc := range testCases { pb := tc.v1.ToProto() @@ -194,7 +194,7 @@ func TestVoteProtobuf(t *testing.T) { v, err := ProofFromProto(pb, false) if tc.expPass { require.NoError(t, err) - require.Equal(t, tc.v1, v, tc.testName) + require.Equal(t, *tc.v1, v, tc.testName) } else { require.Error(t, err) } diff --git a/crypto/merkle/proof_value.go b/crypto/merkle/proof_value.go index d9df9ccb51..995400e0ed 100644 --- a/crypto/merkle/proof_value.go +++ b/crypto/merkle/proof_value.go @@ -51,7 +51,7 @@ func ValueOpDecoder(pop cmtcrypto.ProofOp) (ProofOperator, error) { if err != nil { return nil, err } - return NewValueOp(pop.Key, sp), nil + return NewValueOp(pop.Key, &sp), nil } func (op ValueOp) ProofOp() cmtcrypto.ProofOp { diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index dd0d299353..fd9bcb3ad4 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -490,7 +490,7 @@ func (env *Environment) proveDataRootTuples(tuples []DataRootTuple, height int64 } _, proofs := merkle.ProofsFromByteSlices(dataRootEncodedTuples) //nolint:gosec - return proofs[height-int64(tuples[0].height)], nil + return &proofs[height-int64(tuples[0].height)], nil } // fetchDataRootTuples takes an end exclusive range of heights and fetches its diff --git a/types/part_set.go b/types/part_set.go index 84240303b5..97cdab61bf 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -131,7 +131,7 @@ func PartFromProto(pb *cmtproto.Part) (*Part, error) { } part.Index = pb.Index part.Bytes = pb.Bytes - part.Proof = *proof + part.Proof = proof return part, part.ValidateBasic() } @@ -238,7 +238,7 @@ func NewPartSetFromData(data []byte, partSize uint32) (ops *PartSet, err error) added, err := ops.AddPart(&Part{ Index: uint32(index), Bytes: chunk, - Proof: *proofs[index], + Proof: proofs[index], }) if err != nil { return nil, err @@ -308,7 +308,7 @@ func Encode(ops *PartSet, partSize uint32) (*PartSet, int, error) { added, err := eps.AddPart(&Part{ Index: i, Bytes: chunks[i], - Proof: *eproofs[i], + Proof: eproofs[i], }) if err != nil { return nil, 0, err @@ -390,7 +390,7 @@ func Decode(ops, eps *PartSet, lastPartLen int) (*PartSet, *PartSet, error) { added, err := ops.AddPart(&Part{ Index: uint32(i), Bytes: d, - Proof: *proofs[i], + Proof: proofs[i], }) if err != nil { return nil, nil, err @@ -414,7 +414,7 @@ func Decode(ops, eps *PartSet, lastPartLen int) (*PartSet, *PartSet, error) { added, err := eps.AddPart(&Part{ Index: uint32(i), Bytes: data[int(ops.Total())+i], - Proof: *eproofs[i], + Proof: eproofs[i], }) if err != nil { return nil, nil, err diff --git a/types/results.go b/types/results.go index 2c6728a6d3..156c97b761 100644 --- a/types/results.go +++ b/types/results.go @@ -26,7 +26,7 @@ func (a ABCIResults) Hash() []byte { // ProveResult returns a merkle proof of one result from the set func (a ABCIResults) ProveResult(i int) merkle.Proof { _, proofs := merkle.ProofsFromByteSlices(a.toByteSlices()) - return *proofs[i] + return proofs[i] } func (a ABCIResults) toByteSlices() [][]byte { diff --git a/types/row_proof.go b/types/row_proof.go index 1ecb623696..9f6b80260d 100644 --- a/types/row_proof.go +++ b/types/row_proof.go @@ -16,7 +16,7 @@ type RowProof struct { RowRoots []tmbytes.HexBytes `json:"row_roots"` // Proofs is a list of Merkle proofs where each proof proves that a row // exists in a Merkle tree with a given data root. - Proofs []*merkle.Proof `json:"proofs"` + Proofs []merkle.Proof `json:"proofs"` // StartRow the index of the start row. // Note: currently, StartRow is not validated as part of the proof verification. // If this field is used downstream, Validate(root) should be called along with @@ -66,10 +66,10 @@ func RowProofFromProto(p *tmproto.RowProof) RowProof { return RowProof{} } rowRoots := make([]tmbytes.HexBytes, len(p.RowRoots)) - rowProofs := make([]*merkle.Proof, len(p.Proofs)) + rowProofs := make([]merkle.Proof, len(p.Proofs)) for i := range p.Proofs { rowRoots[i] = p.RowRoots[i] - rowProofs[i] = &merkle.Proof{ + rowProofs[i] = merkle.Proof{ Total: p.Proofs[i].Total, Index: p.Proofs[i].Index, LeafHash: p.Proofs[i].LeafHash, diff --git a/types/row_proof_test.go b/types/row_proof_test.go index 23bceb601e..d1b62a4616 100644 --- a/types/row_proof_test.go +++ b/types/row_proof_test.go @@ -84,7 +84,7 @@ var incorrectRoot = bytes.Repeat([]byte{0}, 32) func validRowProof() RowProof { return RowProof{ RowRoots: tmbytes.FromBytes([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9d, 0xe6, 0x38, 0x91, 0xc1, 0x6, 0xaf, 0x81, 0x75, 0x5a, 0x36, 0xf5, 0xb2, 0x62, 0x1e, 0xfa, 0xb9, 0xb8, 0x73, 0x87, 0xef, 0xe3, 0x6b, 0x33, 0xd8, 0xbf, 0xc9, 0x87, 0x1b, 0x8d, 0xfa, 0x8a}), - Proofs: []*merkle.Proof{ + Proofs: []merkle.Proof{ { Total: 128, Index: 0, @@ -105,7 +105,7 @@ func mismatchedRowRoots() RowProof { func mismatchedProofs() RowProof { rp := validRowProof() - rp.Proofs = []*merkle.Proof{} + rp.Proofs = []merkle.Proof{} return rp } diff --git a/types/tx.go b/types/tx.go index 521c17c971..1dceecfc9a 100644 --- a/types/tx.go +++ b/types/tx.go @@ -171,7 +171,7 @@ func (txs Txs) Proof(i int) TxProof { return TxProof{ RootHash: root, Data: txs[i], - Proof: *proofs[i], + Proof: proofs[i], } } @@ -272,7 +272,7 @@ func TxProofFromProto(pb cmtproto.TxProof) (TxProof, error) { pbtp := TxProof{ RootHash: pb.RootHash, Data: pb.Data, - Proof: *pbProof, + Proof: pbProof, } return pbtp, nil From 47f748c1442a6c0a3ee9a7ba1c50630adea0cd81 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 20 Aug 2025 19:23:24 +0000 Subject: [PATCH 3/4] fix: address review comments - change more proof types to values Co-authored-by: tzdybal <1138893+tzdybal@users.noreply.github.com> --- consensus/propagation/commitment.go | 8 +++--- consensus/propagation/have_wants.go | 6 ++--- consensus/propagation/reactor_test.go | 2 +- consensus/propagation/types/types.go | 32 +++++++++++------------ consensus/propagation/types/types_test.go | 6 ++--- crypto/merkle/proof_test.go | 8 +++++- rpc/core/blocks.go | 8 +++--- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/consensus/propagation/commitment.go b/consensus/propagation/commitment.go index c53cefca5a..5a285ff226 100644 --- a/consensus/propagation/commitment.go +++ b/consensus/propagation/commitment.go @@ -136,16 +136,16 @@ func extractHashes(blocks ...*types.PartSet) [][]byte { return partHashes } -func extractProofs(blocks ...*types.PartSet) []*merkle.Proof { +func extractProofs(blocks ...*types.PartSet) []merkle.Proof { total := uint32(0) for _, block := range blocks { total += block.Total() } - proofs := make([]*merkle.Proof, 0, total) // Preallocate capacity + proofs := make([]merkle.Proof, 0, total) // Preallocate capacity for _, block := range blocks { for i := uint32(0); i < block.Total(); i++ { - proofs = append(proofs, &block.GetPart(int(i)).Proof) + proofs = append(proofs, block.GetPart(int(i)).Proof) } } return proofs @@ -275,7 +275,7 @@ func (blockProp *Reactor) recoverPartsFromMempool(cb *proptypes.CompactBlock) { if partSet.HasPart(int(p.Index)) { continue } - p.Proof = *proofs[p.Index] + p.Proof = proofs[p.Index] added, err := partSet.AddOriginalPart(p) if err != nil { diff --git a/consensus/propagation/have_wants.go b/consensus/propagation/have_wants.go index 799bc73756..43cabe93a8 100644 --- a/consensus/propagation/have_wants.go +++ b/consensus/propagation/have_wants.go @@ -467,14 +467,14 @@ func (blockProp *Reactor) handleRecoveryPart(peer p2p.ID, part *proptypes.Recove // sent during catchup. proof := cb.GetProof(part.Index) if proof == nil { - if part.Proof == nil { + if len(part.Proof.LeafHash) == 0 { blockProp.Logger.Error("proof not found", "peer", peer, "height", part.Height, "round", part.Round, "part", part.Index) return } if len(part.Proof.LeafHash) != tmhash.Size { return } - proof = part.Proof + proof = &part.Proof } added, err := parts.AddPart(part, *proof) @@ -588,7 +588,7 @@ func (blockProp *Reactor) handleRecoveryPart(peer p2p.ID, part *proptypes.Recove return } - go blockProp.clearWants(part, *proof) + go blockProp.clearWants(part, part.Proof) } // clearWants checks the wantState to see if any peers want the given part, if diff --git a/consensus/propagation/reactor_test.go b/consensus/propagation/reactor_test.go index a5d67383c2..247dd7bca1 100644 --- a/consensus/propagation/reactor_test.go +++ b/consensus/propagation/reactor_test.go @@ -643,7 +643,7 @@ func TestConcurrentRequestLimit(t *testing.T) { // testCompactBlock returns a test compact block with the corresponding orignal part set, // parity partset, and proofs. -func testCompactBlock(t *testing.T, height int64, round int32) (*proptypes.CompactBlock, *types.PartSet, *types.PartSet, []*merkle.Proof) { +func testCompactBlock(t *testing.T, height int64, round int32) (*proptypes.CompactBlock, *types.PartSet, *types.PartSet, []merkle.Proof) { ps, err := types.NewPartSetFromData(cmtrand.Bytes(1000), types.BlockPartSizeBytes) require.NoError(t, err) pse, lastLen, err := types.Encode(ps, types.BlockPartSizeBytes) diff --git a/consensus/propagation/types/types.go b/consensus/propagation/types/types.go index 36f884f259..f2216b8dd4 100644 --- a/consensus/propagation/types/types.go +++ b/consensus/propagation/types/types.go @@ -75,7 +75,7 @@ type CompactBlock struct { mtx sync.Mutex // proofsCache is local storage from generated proofs from the PartsHashes. // It must not be included in any serialization. - proofsCache []*merkle.Proof + proofsCache []merkle.Proof } // SignBytes returns the compact block commitment data that @@ -192,7 +192,7 @@ func (c *CompactBlock) ToProto() *protoprop.CompactBlock { // thrown if the proofs are generated and the resulting hashes don't match those // in the compact block. This method should be called upon first receiving a // compact block. -func (c *CompactBlock) Proofs() ([]*merkle.Proof, error) { +func (c *CompactBlock) Proofs() ([]merkle.Proof, error) { c.mtx.Lock() defer c.mtx.Unlock() @@ -206,11 +206,11 @@ func (c *CompactBlock) Proofs() ([]*merkle.Proof, error) { return nil, errors.New("invalid number of partset hashes") } - c.proofsCache = make([]*merkle.Proof, 0, len(c.PartsHashes)) + c.proofsCache = make([]merkle.Proof, 0, len(c.PartsHashes)) root, proofs := merkle.ProofsFromLeafHashes(c.PartsHashes[:total]) for i := range proofs { - c.proofsCache = append(c.proofsCache, &proofs[i]) + c.proofsCache = append(c.proofsCache, proofs[i]) } if !bytes.Equal(root, c.Proposal.BlockID.PartSetHeader.Hash) { @@ -219,7 +219,7 @@ func (c *CompactBlock) Proofs() ([]*merkle.Proof, error) { parityRoot, eproofs := merkle.ProofsFromLeafHashes(c.PartsHashes[total:]) for i := range eproofs { - c.proofsCache = append(c.proofsCache, &eproofs[i]) + c.proofsCache = append(c.proofsCache, eproofs[i]) } if !bytes.Equal(c.BpHash, parityRoot) { @@ -233,12 +233,12 @@ func (c *CompactBlock) GetProof(i uint32) *merkle.Proof { c.mtx.Lock() defer c.mtx.Unlock() if i < uint32(len(c.proofsCache)) { - return c.proofsCache[i] + return &c.proofsCache[i] } return nil } -func (c *CompactBlock) SetProofCache(proofs []*merkle.Proof) { +func (c *CompactBlock) SetProofCache(proofs []merkle.Proof) { c.mtx.Lock() defer c.mtx.Unlock() c.proofsCache = proofs @@ -449,7 +449,7 @@ type RecoveryPart struct { Round int32 Index uint32 Data []byte - Proof *merkle.Proof + Proof merkle.Proof } func (p *RecoveryPart) ValidateBasic() error { @@ -462,14 +462,12 @@ func (p *RecoveryPart) ValidateBasic() error { if len(p.Data) == 0 { return errors.New("RecoveryPart: Data cannot be nil or empty") } - if p.Proof != nil { - if err := p.Proof.ValidateBasic(); err != nil { - return fmt.Errorf("RecoveryPart: invalid proof: %w", err) - } - hash := merkle.LeafHash(p.Data) - if !bytes.Equal(hash, p.Proof.LeafHash) { - return errors.New("RecoveryPart: invalid proof leaf hash") - } + if err := p.Proof.ValidateBasic(); err != nil { + return fmt.Errorf("RecoveryPart: invalid proof: %w", err) + } + hash := merkle.LeafHash(p.Data) + if !bytes.Equal(hash, p.Proof.LeafHash) { + return errors.New("RecoveryPart: invalid proof leaf hash") } return nil } @@ -487,7 +485,7 @@ func RecoveryPartFromProto(r *protoprop.RecoveryPart) (*RecoveryPart, error) { Round: r.Round, Index: r.Index, Data: r.Data, - Proof: &proof, + Proof: proof, } return rp, rp.ValidateBasic() } diff --git a/consensus/propagation/types/types_test.go b/consensus/propagation/types/types_test.go index c9579400e7..900944b55f 100644 --- a/consensus/propagation/types/types_test.go +++ b/consensus/propagation/types/types_test.go @@ -791,7 +791,7 @@ func TestRecoveryPart_ValidateBasic(t *testing.T) { Round: 1, Index: 2, Data: []byte("valid-data"), - Proof: &merkle.Proof{ + Proof: merkle.Proof{ LeafHash: merkle.LeafHash([]byte("valid-data")), }, }, @@ -844,7 +844,7 @@ func TestRecoveryPart_ValidateBasic(t *testing.T) { Round: 1, Index: 0, Data: []byte("data"), - Proof: &merkle.Proof{}, + Proof: merkle.Proof{}, }, expectError: "RecoveryPart: invalid proof", }, @@ -855,7 +855,7 @@ func TestRecoveryPart_ValidateBasic(t *testing.T) { Round: 1, Index: 0, Data: []byte("data"), - Proof: &merkle.Proof{ + Proof: merkle.Proof{ LeafHash: merkle.LeafHash([]byte("invalid")), }, }, diff --git a/crypto/merkle/proof_test.go b/crypto/merkle/proof_test.go index 00a7006dd7..568f9524f8 100644 --- a/crypto/merkle/proof_test.go +++ b/crypto/merkle/proof_test.go @@ -189,8 +189,14 @@ func TestVoteProtobuf(t *testing.T) { {"success", &proofs[0], true}, } for _, tc := range testCases { + if tc.v1 == nil { + // Test nil case + _, err := ProofFromProto(nil, false) + require.Error(t, err) + continue + } + pb := tc.v1.ToProto() - v, err := ProofFromProto(pb, false) if tc.expPass { require.NoError(t, err) diff --git a/rpc/core/blocks.go b/rpc/core/blocks.go index fd9bcb3ad4..8287b90301 100644 --- a/rpc/core/blocks.go +++ b/rpc/core/blocks.go @@ -476,7 +476,7 @@ func (env *Environment) validateDataRootInclusionProofRequest(height uint64, sta } // proveDataRootTuples returns the merkle inclusion proof for a height. -func (env *Environment) proveDataRootTuples(tuples []DataRootTuple, height int64) (*merkle.Proof, error) { +func (env *Environment) proveDataRootTuples(tuples []DataRootTuple, height int64) (merkle.Proof, error) { dataRootEncodedTuples := make([][]byte, 0, len(tuples)) for _, tuple := range tuples { encodedTuple, err := EncodeDataRootTuple( @@ -484,13 +484,13 @@ func (env *Environment) proveDataRootTuples(tuples []DataRootTuple, height int64 tuple.dataRoot, ) if err != nil { - return nil, err + return merkle.Proof{}, err } dataRootEncodedTuples = append(dataRootEncodedTuples, encodedTuple) } _, proofs := merkle.ProofsFromByteSlices(dataRootEncodedTuples) //nolint:gosec - return &proofs[height-int64(tuples[0].height)], nil + return proofs[height-int64(tuples[0].height)], nil } // fetchDataRootTuples takes an end exclusive range of heights and fetches its @@ -544,5 +544,5 @@ func (env *Environment) GenerateDataRootInclusionProof(height int64, start, end if err != nil { return nil, err } - return proof, nil + return &proof, nil } From d0cb4b4409cf5083207e9b97db8d84d4594d24f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 1 Sep 2025 17:43:21 +0000 Subject: [PATCH 4/4] fix: optimize slice allocation to avoid reallocation Co-authored-by: tzdybal <1138893+tzdybal@users.noreply.github.com> --- consensus/propagation/types/types.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/consensus/propagation/types/types.go b/consensus/propagation/types/types.go index f2216b8dd4..c816a5cb55 100644 --- a/consensus/propagation/types/types.go +++ b/consensus/propagation/types/types.go @@ -206,11 +206,11 @@ func (c *CompactBlock) Proofs() ([]merkle.Proof, error) { return nil, errors.New("invalid number of partset hashes") } - c.proofsCache = make([]merkle.Proof, 0, len(c.PartsHashes)) + c.proofsCache = make([]merkle.Proof, len(c.PartsHashes)) root, proofs := merkle.ProofsFromLeafHashes(c.PartsHashes[:total]) for i := range proofs { - c.proofsCache = append(c.proofsCache, proofs[i]) + c.proofsCache[i] = proofs[i] } if !bytes.Equal(root, c.Proposal.BlockID.PartSetHeader.Hash) { @@ -219,7 +219,7 @@ func (c *CompactBlock) Proofs() ([]merkle.Proof, error) { parityRoot, eproofs := merkle.ProofsFromLeafHashes(c.PartsHashes[total:]) for i := range eproofs { - c.proofsCache = append(c.proofsCache, eproofs[i]) + c.proofsCache[int(total)+i] = eproofs[i] } if !bytes.Equal(c.BpHash, parityRoot) {