From 672d09ddce32677d21343ec1bec6ed54ab7b2d10 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 19 Apr 2024 19:34:55 +0400 Subject: [PATCH 1/2] fix verifyEncoding to always set rebuild share back --- extendeddatacrossword.go | 22 ++++++++++------------ extendeddatacrossword_test.go | 33 +++++++++++++++++++++++++++++++++ rsmt2d_test.go | 7 +++++-- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/extendeddatacrossword.go b/extendeddatacrossword.go index 7114321..b44442e 100644 --- a/extendeddatacrossword.go +++ b/extendeddatacrossword.go @@ -378,11 +378,8 @@ func (eds *ExtendedDataSquare) preRepairSanityCheck( return nil }) errs.Go(func() error { - parityShares, err := eds.codec.Encode(eds.rowSlice(i, 0, eds.originalDataWidth)) + err := eds.verifyEncoding(eds.row(i), noShareInsertion, nil) if err != nil { - return err - } - if !bytes.Equal(flattenShares(parityShares), flattenShares(eds.rowSlice(i, eds.originalDataWidth, eds.originalDataWidth))) { return &ErrByzantineData{Row, i, eds.row(i)} } return nil @@ -407,12 +404,8 @@ func (eds *ExtendedDataSquare) preRepairSanityCheck( return nil }) errs.Go(func() error { - // check if we take the first half of the col and encode it, we get the second half - parityShares, err := eds.codec.Encode(eds.colSlice(0, i, eds.originalDataWidth)) + err := eds.verifyEncoding(eds.col(i), noShareInsertion, nil) if err != nil { - return err - } - if !bytes.Equal(flattenShares(parityShares), flattenShares(eds.colSlice(eds.originalDataWidth, i, eds.originalDataWidth))) { return &ErrByzantineData{Col, i, eds.col(i)} } return nil @@ -473,7 +466,14 @@ func (eds *ExtendedDataSquare) computeSharesRootWithRebuiltShare(shares [][]byte // verifyEncoding checks the Reed-Solomon encoding of the provided data. func (eds *ExtendedDataSquare) verifyEncoding(data [][]byte, rebuiltIndex int, rebuiltShare []byte) error { - data[rebuiltIndex] = rebuiltShare + if rebuiltShare != nil && rebuiltIndex >= 0 { + data[rebuiltIndex] = rebuiltShare + defer func() { + // revert the change to the data slice after the verification + data[rebuiltIndex] = nil + }() + } + half := len(data) / 2 original := data[:half] parity, err := eds.codec.Encode(original) @@ -483,10 +483,8 @@ func (eds *ExtendedDataSquare) verifyEncoding(data [][]byte, rebuiltIndex int, r for i := half; i < len(data); i++ { if !bytes.Equal(data[i], parity[i-half]) { - data[rebuiltIndex] = nil return errors.New("parity data does not match encoded data") } } - return nil } diff --git a/extendeddatacrossword_test.go b/extendeddatacrossword_test.go index 4ad7be3..4fb8566 100644 --- a/extendeddatacrossword_test.go +++ b/extendeddatacrossword_test.go @@ -78,6 +78,39 @@ func TestRepairExtendedDataSquare(t *testing.T) { t.Errorf("did not return an error on trying to repair an unrepairable square") } }) + + t.Run("repair in random order", func(t *testing.T) { + for i := 0; i < 100; i++ { + newEds, err := NewExtendedDataSquare(codec, NewDefaultTree, original.Width(), shareSize) + require.NoError(t, err) + // Randomly set shares in the newEds from the original and repair. + for { + x := rand.Intn(int(original.Width())) + y := rand.Intn(int(original.Width())) + if newEds.GetCell(uint(x), uint(y)) != nil { + continue + } + err = newEds.SetCell(uint(x), uint(y), original.GetCell(uint(x), uint(y))) + require.NoError(t, err) + + // Repair square. + err = newEds.Repair(rowRoots, colRoots) + if errors.Is(err, ErrUnrepairableDataSquare) { + continue + } + require.NoError(t, err) + break + } + + require.True(t, newEds.Equals(original)) + newRowRoots, err := newEds.RowRoots() + require.NoError(t, err) + require.Equal(t, rowRoots, newRowRoots) + newColRoots, err := newEds.ColRoots() + require.NoError(t, err) + require.Equal(t, colRoots, newColRoots) + } + }) } func TestValidFraudProof(t *testing.T) { diff --git a/rsmt2d_test.go b/rsmt2d_test.go index f4062db..3e158f7 100644 --- a/rsmt2d_test.go +++ b/rsmt2d_test.go @@ -56,13 +56,13 @@ func TestEdsRepairRoundtripSimple(t *testing.T) { flattened[12], flattened[13] = nil, nil // Re-import the data square. - eds, err = rsmt2d.ImportExtendedDataSquare(flattened, tt.codec, rsmt2d.NewDefaultTree) + newEds, err := rsmt2d.ImportExtendedDataSquare(flattened, tt.codec, rsmt2d.NewDefaultTree) if err != nil { t.Errorf("ImportExtendedDataSquare failed: %v", err) } // Repair square. - err = eds.Repair( + err = newEds.Repair( rowRoots, colRoots, ) @@ -71,6 +71,9 @@ func TestEdsRepairRoundtripSimple(t *testing.T) { // See extendeddatacrossword_test.go t.Errorf("RepairExtendedDataSquare failed: %v", err) } + if !newEds.Equals(eds) { + t.Errorf("Repaired ExtendedDataSquare does not match original") + } }) } } From 38f58f58fd863ba0db87099fa02734b54b1696c7 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 19 Apr 2024 20:13:20 +0400 Subject: [PATCH 2/2] revert changes to unrelated test --- rsmt2d_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/rsmt2d_test.go b/rsmt2d_test.go index 3e158f7..f4062db 100644 --- a/rsmt2d_test.go +++ b/rsmt2d_test.go @@ -56,13 +56,13 @@ func TestEdsRepairRoundtripSimple(t *testing.T) { flattened[12], flattened[13] = nil, nil // Re-import the data square. - newEds, err := rsmt2d.ImportExtendedDataSquare(flattened, tt.codec, rsmt2d.NewDefaultTree) + eds, err = rsmt2d.ImportExtendedDataSquare(flattened, tt.codec, rsmt2d.NewDefaultTree) if err != nil { t.Errorf("ImportExtendedDataSquare failed: %v", err) } // Repair square. - err = newEds.Repair( + err = eds.Repair( rowRoots, colRoots, ) @@ -71,9 +71,6 @@ func TestEdsRepairRoundtripSimple(t *testing.T) { // See extendeddatacrossword_test.go t.Errorf("RepairExtendedDataSquare failed: %v", err) } - if !newEds.Equals(eds) { - t.Errorf("Repaired ExtendedDataSquare does not match original") - } }) } }