From 91ef76a9a4bea74904a8517000299f13cd98d01e Mon Sep 17 00:00:00 2001 From: Dan Laine Date: Tue, 23 May 2023 10:04:28 -0400 Subject: [PATCH] remove EncodeProof, DecodeProof, unused helpers --- x/merkledb/codec.go | 211 +++------------------------------------ x/merkledb/codec_test.go | 117 ---------------------- x/merkledb/proof_test.go | 90 ----------------- 3 files changed, 14 insertions(+), 404 deletions(-) diff --git a/x/merkledb/codec.go b/x/merkledb/codec.go index d88fa4ef39a1..721603280474 100644 --- a/x/merkledb/codec.go +++ b/x/merkledb/codec.go @@ -46,21 +46,20 @@ var ( trueBytes = []byte{trueByte} falseBytes = []byte{falseByte} - errUnknownVersion = errors.New("unknown codec version") - errEncodeNil = errors.New("can't encode nil pointer or interface") - errDecodeNil = errors.New("can't decode nil") - errNegativeProofPathNodes = errors.New("negative proof path length") - errNegativeNumChildren = errors.New("number of children is negative") - errTooManyChildren = fmt.Errorf("length of children list is larger than branching factor of %d", NodeBranchFactor) - errChildIndexTooLarge = fmt.Errorf("invalid child index. Must be less than branching factor of %d", NodeBranchFactor) - errNegativeNibbleLength = errors.New("nibble length is negative") - errIntTooLarge = errors.New("integer too large to be decoded") - errLeadingZeroes = errors.New("varint has leading zeroes") - errInvalidBool = errors.New("decoded bool is neither true nor false") - errNonZeroNibblePadding = errors.New("nibbles should be padded with 0s") - errExtraSpace = errors.New("trailing buffer space") - errNegativeSliceLength = errors.New("negative slice length") - errInvalidCodecVersion = errors.New("invalid codec version") + errUnknownVersion = errors.New("unknown codec version") + errEncodeNil = errors.New("can't encode nil pointer or interface") + errDecodeNil = errors.New("can't decode nil") + errNegativeNumChildren = errors.New("number of children is negative") + errTooManyChildren = fmt.Errorf("length of children list is larger than branching factor of %d", NodeBranchFactor) + errChildIndexTooLarge = fmt.Errorf("invalid child index. Must be less than branching factor of %d", NodeBranchFactor) + errNegativeNibbleLength = errors.New("nibble length is negative") + errIntTooLarge = errors.New("integer too large to be decoded") + errLeadingZeroes = errors.New("varint has leading zeroes") + errInvalidBool = errors.New("decoded bool is neither true nor false") + errNonZeroNibblePadding = errors.New("nibbles should be padded with 0s") + errExtraSpace = errors.New("trailing buffer space") + errNegativeSliceLength = errors.New("negative slice length") + errInvalidCodecVersion = errors.New("invalid codec version") ) // EncoderDecoder defines the interface needed by merkleDB to marshal @@ -71,15 +70,11 @@ type EncoderDecoder interface { } type Encoder interface { - EncodeProof(version uint16, p *Proof) ([]byte, error) - encodeDBNode(version uint16, n *dbNode) ([]byte, error) encodeHashValues(version uint16, hv *hashValues) ([]byte, error) } type Decoder interface { - DecodeProof(bytes []byte, p *Proof) (uint16, error) - decodeDBNode(bytes []byte, n *dbNode) (uint16, error) } @@ -97,31 +92,6 @@ type codecImpl struct { varIntPool sync.Pool } -func (c *codecImpl) EncodeProof(version uint16, proof *Proof) ([]byte, error) { - if proof == nil { - return nil, errEncodeNil - } - - if version != codecVersion { - return nil, fmt.Errorf("%w: %d", errUnknownVersion, version) - } - - buf := &bytes.Buffer{} - if err := c.encodeInt(buf, int(version)); err != nil { - return nil, err - } - if err := c.encodeProofPath(buf, proof.Path); err != nil { - return nil, err - } - if err := c.encodeByteSlice(buf, proof.Key); err != nil { - return nil, err - } - if err := c.encodeMaybeByteSlice(buf, proof.Value); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - func (c *codecImpl) encodeDBNode(version uint16, n *dbNode) ([]byte, error) { if n == nil { return nil, errEncodeNil @@ -200,40 +170,6 @@ func (c *codecImpl) encodeHashValues(version uint16, hv *hashValues) ([]byte, er return buf.Bytes(), nil } -func (c *codecImpl) DecodeProof(b []byte, proof *Proof) (uint16, error) { - if proof == nil { - return 0, errDecodeNil - } - if minProofLen > len(b) { - return 0, io.ErrUnexpectedEOF - } - - var ( - err error - src = bytes.NewReader(b) - ) - gotCodecVersion, err := c.decodeInt(src) - if err != nil { - return 0, err - } - if codecVersion != gotCodecVersion { - return 0, fmt.Errorf("%w: %d", errInvalidCodecVersion, gotCodecVersion) - } - if proof.Path, err = c.decodeProofPath(src); err != nil { - return 0, err - } - if proof.Key, err = c.decodeByteSlice(src); err != nil { - return 0, err - } - if proof.Value, err = c.decodeMaybeByteSlice(src); err != nil { - return 0, err - } - if src.Len() != 0 { - return 0, errExtraSpace - } - return codecVersion, nil -} - func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) (uint16, error) { if n == nil { return 0, errDecodeNil @@ -467,125 +403,6 @@ func (*codecImpl) decodeID(src *bytes.Reader) (ids.ID, error) { return id, nil } -// Assumes a proof path has > 0 nodes. -func (c *codecImpl) decodeProofPath(src *bytes.Reader) ([]ProofNode, error) { - if minProofPathLen > src.Len() { - return nil, io.ErrUnexpectedEOF - } - - numProofNodes, err := c.decodeInt(src) - if err != nil { - return nil, err - } - if numProofNodes < 0 { - return nil, errNegativeProofPathNodes - } - if numProofNodes > src.Len()/minProofNodeLen { - return nil, io.ErrUnexpectedEOF - } - result := make([]ProofNode, numProofNodes) - for i := 0; i < numProofNodes; i++ { - if result[i], err = c.decodeProofNode(src); err != nil { - return nil, err - } - } - return result, nil -} - -// Invariant: len(path) > 0. -func (c *codecImpl) encodeProofPath(dst io.Writer, path []ProofNode) error { - if err := c.encodeInt(dst, len(path)); err != nil { - return err - } - for _, proofNode := range path { - if err := c.encodeProofNode(proofNode, dst); err != nil { - return err - } - } - return nil -} - -func (c *codecImpl) decodeProofNode(src *bytes.Reader) (ProofNode, error) { - if minProofNodeLen > src.Len() { - return ProofNode{}, io.ErrUnexpectedEOF - } - - var ( - result ProofNode - err error - ) - if result.KeyPath, err = c.decodeSerializedPath(src); err != nil { - return result, err - } - if result.ValueOrHash, err = c.decodeMaybeByteSlice(src); err != nil { - return result, err - } - numChildren, err := c.decodeInt(src) - if err != nil { - return result, err - } - switch { - case numChildren < 0: - return result, errNegativeNumChildren - case numChildren > NodeBranchFactor: - return result, errTooManyChildren - case numChildren > src.Len()/minProofNodeChildLen: - return result, io.ErrUnexpectedEOF - } - - result.Children = make(map[byte]ids.ID, numChildren) - previousChild := -1 - for addedEntries := 0; addedEntries < numChildren; addedEntries++ { - index, err := c.decodeInt(src) - if err != nil { - return result, err - } - if index <= previousChild || index >= NodeBranchFactor { - return result, errChildIndexTooLarge - } - previousChild = index - - childID, err := c.decodeID(src) - if err != nil { - return result, err - } - result.Children[byte(index)] = childID - } - return result, nil -} - -func (c *codecImpl) encodeProofNode(pn ProofNode, dst io.Writer) error { - if err := c.encodeSerializedPath(pn.KeyPath, dst); err != nil { - return err - } - if err := c.encodeMaybeByteSlice(dst, pn.ValueOrHash); err != nil { - return err - } - if err := c.encodeInt(dst, len(pn.Children)); err != nil { - return err - } - // ensure this is in order - childrenCount := 0 - for index := byte(0); index < NodeBranchFactor; index++ { - childID, ok := pn.Children[index] - if !ok { - continue - } - childrenCount++ - if err := c.encodeInt(dst, int(index)); err != nil { - return err - } - if _, err := dst.Write(childID[:]); err != nil { - return err - } - } - // there are children present with index >= NodeBranchFactor - if childrenCount != len(pn.Children) { - return errChildIndexTooLarge - } - return nil -} - func (c *codecImpl) encodeSerializedPath(s SerializedPath, dst io.Writer) error { if err := c.encodeInt(dst, s.NibbleLength); err != nil { return err diff --git a/x/merkledb/codec_test.go b/x/merkledb/codec_test.go index 53708ed92374..5d35667ae8ef 100644 --- a/x/merkledb/codec_test.go +++ b/x/merkledb/codec_test.go @@ -198,68 +198,6 @@ func FuzzCodecSerializedPath(f *testing.F) { ) } -func FuzzCodecProofCanonical(f *testing.F) { - f.Add( - []byte{ - // RootID: - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - // Path: - // Num proof nodes = 1 - 0x02, - // Key Path: - // Nibble Length: - 0x00, - // Value: - // Has Value = false - 0x00, - // Num Children = 2 - 0x04, - // Child 0: - // index = 0 - 0x00, - // childID: - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - // Child 1: - // index = 0 <- should fail - 0x00, - // childID: - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - // Key: - // length = 0 - 0x00, - }, - ) - f.Fuzz( - func( - t *testing.T, - b []byte, - ) { - require := require.New(t) - - codec := Codec.(*codecImpl) - proof := &Proof{} - got, err := codec.DecodeProof(b, proof) - if err != nil { - return - } - - // Encoding [proof] should be the same as [b]. - buf, err := codec.EncodeProof(got, proof) - require.NoError(err) - require.Equal(b, buf) - }, - ) -} - func FuzzCodecDBNodeCanonical(f *testing.F) { f.Fuzz( func( @@ -283,47 +221,6 @@ func FuzzCodecDBNodeCanonical(f *testing.F) { ) } -func FuzzCodecProofDeterministic(f *testing.F) { - f.Fuzz( - func( - t *testing.T, - randSeed int, - key []byte, - numProofNodes uint, - ) { - require := require.New(t) - - r := rand.New(rand.NewSource(int64(randSeed))) // #nosec G404 - - proofNodes := make([]ProofNode, numProofNodes) - for i := range proofNodes { - proofNodes[i] = newRandomProofNode(r) - } - - proof := Proof{ - Path: proofNodes, - Key: key, - } - - proofBytes, err := Codec.EncodeProof(Version, &proof) - require.NoError(err) - - var gotProof Proof - gotVersion, err := Codec.DecodeProof(proofBytes, &gotProof) - require.NoError(err) - require.Equal(Version, gotVersion) - - nilEmptySlices(&proof) - nilEmptySlices(&gotProof) - require.Equal(proof, gotProof) - - proofBytes2, err := Codec.EncodeProof(Version, &gotProof) - require.NoError(err) - require.Equal(proofBytes, proofBytes2) - }, - ) -} - func FuzzCodecDBNodeDeterministic(f *testing.F) { f.Fuzz( func( @@ -389,20 +286,6 @@ func FuzzCodecDBNodeDeterministic(f *testing.F) { ) } -func TestCodec_DecodeProof(t *testing.T) { - require := require.New(t) - - _, err := Codec.DecodeProof([]byte{1}, nil) - require.ErrorIs(err, errDecodeNil) - - var ( - proof Proof - tooShortBytes = make([]byte, minProofLen-1) - ) - _, err = Codec.DecodeProof(tooShortBytes, &proof) - require.ErrorIs(err, io.ErrUnexpectedEOF) -} - func TestCodec_DecodeDBNode(t *testing.T) { require := require.New(t) diff --git a/x/merkledb/proof_test.go b/x/merkledb/proof_test.go index af5e7c54486c..2cb6aad2489e 100644 --- a/x/merkledb/proof_test.go +++ b/x/merkledb/proof_test.go @@ -4,9 +4,7 @@ package merkledb import ( - "bytes" "context" - "io" "math/rand" "testing" @@ -42,100 +40,12 @@ func writeBasicBatch(t *testing.T, db *Database) { require.NoError(t, batch.Write()) } -func Test_Proof_Marshal(t *testing.T) { - require := require.New(t) - dbTrie, err := getBasicDB() - require.NoError(err) - require.NotNil(dbTrie) - writeBasicBatch(t, dbTrie) - - proof, err := dbTrie.GetProof(context.Background(), []byte{1}) - require.NoError(err) - require.NotNil(proof) - - proofBytes, err := Codec.EncodeProof(Version, proof) - require.NoError(err) - - parsedProof := &Proof{} - _, err = Codec.DecodeProof(proofBytes, parsedProof) - require.NoError(err) - - verifyPath(t, proof.Path, parsedProof.Path) - require.Equal([]byte{1}, proof.Value.value) -} - func Test_Proof_Empty(t *testing.T) { proof := &Proof{} err := proof.Verify(context.Background(), ids.Empty) require.ErrorIs(t, err, ErrNoProof) } -func Test_Proof_MissingValue(t *testing.T) { - trie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, trie) - - require.NoError(t, trie.Insert(context.Background(), []byte{1}, []byte{0})) - require.NoError(t, trie.Insert(context.Background(), []byte{1, 2}, []byte{0})) - require.NoError(t, trie.Insert(context.Background(), []byte{1, 2, 4}, []byte{0})) - require.NoError(t, trie.Insert(context.Background(), []byte{1, 3}, []byte{0})) - - // get a proof for a value not in the db - proof, err := trie.GetProof(context.Background(), []byte{1, 2, 3}) - require.NoError(t, err) - require.NotNil(t, proof) - - require.True(t, proof.Value.IsNothing()) - - proofBytes, err := Codec.EncodeProof(Version, proof) - require.NoError(t, err) - - parsedProof := &Proof{} - _, err = Codec.DecodeProof(proofBytes, parsedProof) - require.NoError(t, err) - - verifyPath(t, proof.Path, parsedProof.Path) -} - -func Test_Proof_Marshal_Errors(t *testing.T) { - trie, err := getBasicDB() - require.NoError(t, err) - require.NotNil(t, trie) - - writeBasicBatch(t, trie) - - proof, err := trie.GetProof(context.Background(), []byte{1}) - require.NoError(t, err) - require.NotNil(t, proof) - - proofBytes, err := Codec.EncodeProof(Version, proof) - require.NoError(t, err) - - for i := 1; i < len(proofBytes); i++ { - broken := proofBytes[:i] - parsed := &Proof{} - _, err = Codec.DecodeProof(broken, parsed) - require.ErrorIs(t, err, io.ErrUnexpectedEOF) - } - - // add a child at an invalid index - proof.Path[0].Children[255] = ids.Empty - _, err = Codec.EncodeProof(Version, proof) - require.ErrorIs(t, err, errChildIndexTooLarge) -} - -func verifyPath(t *testing.T, path1, path2 []ProofNode) { - require.Len(t, path2, len(path1)) - for i := range path1 { - require.True(t, bytes.Equal(path1[i].KeyPath.Value, path2[i].KeyPath.Value)) - require.Equal(t, path1[i].KeyPath.hasOddLength(), path2[i].KeyPath.hasOddLength()) - require.True(t, bytes.Equal(path1[i].ValueOrHash.value, path2[i].ValueOrHash.value)) - for childIndex := range path1[i].Children { - require.Equal(t, path1[i].Children[childIndex], path2[i].Children[childIndex]) - } - } -} - func Test_Proof_Verify_Bad_Data(t *testing.T) { type test struct { name string