github.com/MetalBlockchain/metalgo@v1.11.9/x/merkledb/proof_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package merkledb
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"math/rand"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/MetalBlockchain/metalgo/database"
    16  	"github.com/MetalBlockchain/metalgo/ids"
    17  	"github.com/MetalBlockchain/metalgo/utils/hashing"
    18  	"github.com/MetalBlockchain/metalgo/utils/maybe"
    19  	"github.com/MetalBlockchain/metalgo/utils/set"
    20  
    21  	pb "github.com/MetalBlockchain/metalgo/proto/pb/sync"
    22  )
    23  
    24  func Test_Proof_Empty(t *testing.T) {
    25  	proof := &Proof{}
    26  	err := proof.Verify(context.Background(), ids.Empty, 4, DefaultHasher)
    27  	require.ErrorIs(t, err, ErrEmptyProof)
    28  }
    29  
    30  func Test_Proof_Simple(t *testing.T) {
    31  	require := require.New(t)
    32  
    33  	db, err := getBasicDB()
    34  	require.NoError(err)
    35  
    36  	ctx := context.Background()
    37  	require.NoError(db.PutContext(ctx, []byte{}, []byte{1}))
    38  	require.NoError(db.PutContext(ctx, []byte{0}, []byte{2}))
    39  
    40  	expectedRoot, err := db.GetMerkleRoot(ctx)
    41  	require.NoError(err)
    42  
    43  	proof, err := db.GetProof(ctx, []byte{})
    44  	require.NoError(err)
    45  
    46  	require.NoError(proof.Verify(ctx, expectedRoot, db.tokenSize, db.hasher))
    47  }
    48  
    49  func Test_Proof_Verify_Bad_Data(t *testing.T) {
    50  	type test struct {
    51  		name        string
    52  		malform     func(proof *Proof)
    53  		expectedErr error
    54  	}
    55  
    56  	tests := []test{
    57  		{
    58  			name:        "happyPath",
    59  			malform:     func(*Proof) {},
    60  			expectedErr: nil,
    61  		},
    62  		{
    63  			name: "empty",
    64  			malform: func(proof *Proof) {
    65  				proof.Path = nil
    66  			},
    67  			expectedErr: ErrEmptyProof,
    68  		},
    69  		{
    70  			name: "odd length key path with value",
    71  			malform: func(proof *Proof) {
    72  				proof.Path[0].ValueOrHash = maybe.Some([]byte{1, 2})
    73  			},
    74  			expectedErr: ErrPartialByteLengthWithValue,
    75  		},
    76  		{
    77  			name: "last proof node has missing value",
    78  			malform: func(proof *Proof) {
    79  				proof.Path[len(proof.Path)-1].ValueOrHash = maybe.Nothing[[]byte]()
    80  			},
    81  			expectedErr: ErrProofValueDoesntMatch,
    82  		},
    83  		{
    84  			name: "missing value on proof",
    85  			malform: func(proof *Proof) {
    86  				proof.Value = maybe.Nothing[[]byte]()
    87  			},
    88  			expectedErr: ErrProofValueDoesntMatch,
    89  		},
    90  		{
    91  			name: "mismatched value on proof",
    92  			malform: func(proof *Proof) {
    93  				proof.Value = maybe.Some([]byte{10})
    94  			},
    95  			expectedErr: ErrProofValueDoesntMatch,
    96  		},
    97  		{
    98  			name: "value of exclusion proof",
    99  			malform: func(proof *Proof) {
   100  				// remove the value node to make it look like it is an exclusion proof
   101  				proof.Path = proof.Path[:len(proof.Path)-1]
   102  			},
   103  			expectedErr: ErrProofValueDoesntMatch,
   104  		},
   105  	}
   106  
   107  	for _, tt := range tests {
   108  		t.Run(tt.name, func(t *testing.T) {
   109  			require := require.New(t)
   110  
   111  			db, err := getBasicDB()
   112  			require.NoError(err)
   113  
   114  			writeBasicBatch(t, db)
   115  
   116  			proof, err := db.GetProof(context.Background(), []byte{2})
   117  			require.NoError(err)
   118  			require.NotNil(proof)
   119  
   120  			tt.malform(proof)
   121  
   122  			err = proof.Verify(context.Background(), db.getMerkleRoot(), db.tokenSize, db.hasher)
   123  			require.ErrorIs(err, tt.expectedErr)
   124  		})
   125  	}
   126  }
   127  
   128  func Test_Proof_ValueOrHashMatches(t *testing.T) {
   129  	require := require.New(t)
   130  
   131  	require.True(valueOrHashMatches(SHA256Hasher, maybe.Some([]byte{0}), maybe.Some([]byte{0})))
   132  	require.False(valueOrHashMatches(SHA256Hasher, maybe.Nothing[[]byte](), maybe.Some(hashing.ComputeHash256([]byte{0}))))
   133  	require.True(valueOrHashMatches(SHA256Hasher, maybe.Nothing[[]byte](), maybe.Nothing[[]byte]()))
   134  
   135  	require.False(valueOrHashMatches(SHA256Hasher, maybe.Some([]byte{0}), maybe.Nothing[[]byte]()))
   136  	require.False(valueOrHashMatches(SHA256Hasher, maybe.Nothing[[]byte](), maybe.Some([]byte{0})))
   137  	require.False(valueOrHashMatches(SHA256Hasher, maybe.Nothing[[]byte](), maybe.Some(hashing.ComputeHash256([]byte{1}))))
   138  	require.False(valueOrHashMatches(SHA256Hasher, maybe.Some(hashing.ComputeHash256([]byte{0})), maybe.Nothing[[]byte]()))
   139  }
   140  
   141  func Test_RangeProof_Extra_Value(t *testing.T) {
   142  	require := require.New(t)
   143  
   144  	db, err := getBasicDB()
   145  	require.NoError(err)
   146  	writeBasicBatch(t, db)
   147  
   148  	val, err := db.Get([]byte{2})
   149  	require.NoError(err)
   150  	require.Equal([]byte{2}, val)
   151  
   152  	proof, err := db.GetRangeProof(context.Background(), maybe.Some([]byte{1}), maybe.Some([]byte{5, 5}), 10)
   153  	require.NoError(err)
   154  	require.NotNil(proof)
   155  
   156  	require.NoError(proof.Verify(
   157  		context.Background(),
   158  		maybe.Some([]byte{1}),
   159  		maybe.Some([]byte{5, 5}),
   160  		db.rootID,
   161  		db.tokenSize,
   162  		db.hasher,
   163  	))
   164  
   165  	proof.KeyValues = append(proof.KeyValues, KeyValue{Key: []byte{5}, Value: []byte{5}})
   166  
   167  	err = proof.Verify(
   168  		context.Background(),
   169  		maybe.Some([]byte{1}),
   170  		maybe.Some([]byte{5, 5}),
   171  		db.rootID,
   172  		db.tokenSize,
   173  		db.hasher,
   174  	)
   175  	require.ErrorIs(err, ErrInvalidProof)
   176  }
   177  
   178  func Test_RangeProof_Verify_Bad_Data(t *testing.T) {
   179  	type test struct {
   180  		name        string
   181  		malform     func(proof *RangeProof)
   182  		expectedErr error
   183  	}
   184  
   185  	tests := []test{
   186  		{
   187  			name:        "happyPath",
   188  			malform:     func(*RangeProof) {},
   189  			expectedErr: nil,
   190  		},
   191  		{
   192  			name: "empty",
   193  			malform: func(proof *RangeProof) {
   194  				proof.KeyValues = nil
   195  				proof.StartProof = nil
   196  				proof.EndProof = nil
   197  			},
   198  			expectedErr: ErrEmptyProof,
   199  		},
   200  		{
   201  			name: "StartProof: last proof node has missing value",
   202  			malform: func(proof *RangeProof) {
   203  				proof.StartProof[len(proof.StartProof)-1].ValueOrHash = maybe.Nothing[[]byte]()
   204  			},
   205  			expectedErr: ErrProofValueDoesntMatch,
   206  		},
   207  		{
   208  			name: "EndProof: odd length key path with value",
   209  			malform: func(proof *RangeProof) {
   210  				proof.EndProof[0].ValueOrHash = maybe.Some([]byte{1, 2})
   211  			},
   212  			expectedErr: ErrPartialByteLengthWithValue,
   213  		},
   214  		{
   215  			name: "EndProof: last proof node has missing value",
   216  			malform: func(proof *RangeProof) {
   217  				proof.EndProof[len(proof.EndProof)-1].ValueOrHash = maybe.Nothing[[]byte]()
   218  			},
   219  			expectedErr: ErrProofValueDoesntMatch,
   220  		},
   221  		{
   222  			name: "missing key/value",
   223  			malform: func(proof *RangeProof) {
   224  				proof.KeyValues = proof.KeyValues[1:]
   225  			},
   226  			expectedErr: ErrProofNodeHasUnincludedValue,
   227  		},
   228  	}
   229  
   230  	for _, tt := range tests {
   231  		t.Run(tt.name, func(t *testing.T) {
   232  			require := require.New(t)
   233  
   234  			db, err := getBasicDB()
   235  			require.NoError(err)
   236  			writeBasicBatch(t, db)
   237  
   238  			proof, err := db.GetRangeProof(context.Background(), maybe.Some([]byte{2}), maybe.Some([]byte{3, 0}), 50)
   239  			require.NoError(err)
   240  			require.NotNil(proof)
   241  
   242  			tt.malform(proof)
   243  
   244  			err = proof.Verify(context.Background(), maybe.Some([]byte{2}), maybe.Some([]byte{3, 0}), db.getMerkleRoot(), db.tokenSize, db.hasher)
   245  			require.ErrorIs(err, tt.expectedErr)
   246  		})
   247  	}
   248  }
   249  
   250  func Test_RangeProof_MaxLength(t *testing.T) {
   251  	require := require.New(t)
   252  
   253  	dbTrie, err := getBasicDB()
   254  	require.NoError(err)
   255  	require.NotNil(dbTrie)
   256  	trie, err := dbTrie.NewView(context.Background(), ViewChanges{})
   257  	require.NoError(err)
   258  
   259  	_, err = trie.GetRangeProof(context.Background(), maybe.Nothing[[]byte](), maybe.Nothing[[]byte](), -1)
   260  	require.ErrorIs(err, ErrInvalidMaxLength)
   261  
   262  	_, err = trie.GetRangeProof(context.Background(), maybe.Nothing[[]byte](), maybe.Nothing[[]byte](), 0)
   263  	require.ErrorIs(err, ErrInvalidMaxLength)
   264  }
   265  
   266  func Test_Proof(t *testing.T) {
   267  	require := require.New(t)
   268  
   269  	dbTrie, err := getBasicDB()
   270  	require.NoError(err)
   271  	require.NotNil(dbTrie)
   272  	trie, err := dbTrie.NewView(
   273  		context.Background(),
   274  		ViewChanges{
   275  			BatchOps: []database.BatchOp{
   276  				{Key: []byte("key"), Value: []byte("value")},
   277  				{Key: []byte("key0"), Value: []byte("value0")},
   278  				{Key: []byte("key1"), Value: []byte("value1")},
   279  				{Key: []byte("key2"), Value: []byte("value2")},
   280  				{Key: []byte("key3"), Value: []byte("value3")},
   281  				{Key: []byte("key4"), Value: []byte("value4")},
   282  			},
   283  		},
   284  	)
   285  	require.NoError(err)
   286  
   287  	_, err = trie.GetMerkleRoot(context.Background())
   288  	require.NoError(err)
   289  	proof, err := trie.GetProof(context.Background(), []byte("key1"))
   290  	require.NoError(err)
   291  	require.NotNil(proof)
   292  
   293  	require.Len(proof.Path, 3)
   294  
   295  	require.Equal(ToKey([]byte("key")), proof.Path[0].Key)
   296  	require.Equal(maybe.Some([]byte("value")), proof.Path[0].ValueOrHash)
   297  	require.Equal(ToKey([]byte("key0")).Take(28), proof.Path[1].Key)
   298  	require.True(proof.Path[1].ValueOrHash.IsNothing()) // intermediate node
   299  	require.Equal(ToKey([]byte("key1")), proof.Path[2].Key)
   300  	require.Equal(maybe.Some([]byte("value1")), proof.Path[2].ValueOrHash)
   301  
   302  	expectedRootID, err := trie.GetMerkleRoot(context.Background())
   303  	require.NoError(err)
   304  	require.NoError(proof.Verify(context.Background(), expectedRootID, dbTrie.tokenSize, dbTrie.hasher))
   305  
   306  	proof.Path[0].Key = ToKey([]byte("key1"))
   307  	err = proof.Verify(context.Background(), expectedRootID, dbTrie.tokenSize, dbTrie.hasher)
   308  	require.ErrorIs(err, ErrProofNodeNotForKey)
   309  }
   310  
   311  func Test_RangeProof_Syntactic_Verify(t *testing.T) {
   312  	type test struct {
   313  		name        string
   314  		start       maybe.Maybe[[]byte]
   315  		end         maybe.Maybe[[]byte]
   316  		proof       *RangeProof
   317  		expectedErr error
   318  	}
   319  
   320  	tests := []test{
   321  		{
   322  			name:        "start > end",
   323  			start:       maybe.Some([]byte{1}),
   324  			end:         maybe.Some([]byte{0}),
   325  			proof:       &RangeProof{},
   326  			expectedErr: ErrStartAfterEnd,
   327  		},
   328  		{
   329  			name:        "empty",
   330  			start:       maybe.Some([]byte{1}),
   331  			end:         maybe.Nothing[[]byte](),
   332  			proof:       &RangeProof{},
   333  			expectedErr: ErrEmptyProof,
   334  		},
   335  		{
   336  			name:  "unexpected end proof",
   337  			start: maybe.Some([]byte{1}),
   338  			end:   maybe.Nothing[[]byte](),
   339  			proof: &RangeProof{
   340  				StartProof: []ProofNode{{}},
   341  				EndProof:   []ProofNode{{}},
   342  			},
   343  			expectedErr: ErrUnexpectedEndProof,
   344  		},
   345  		{
   346  			name:  "no end proof; has end bound",
   347  			start: maybe.Some([]byte{1}),
   348  			end:   maybe.Some([]byte{1}),
   349  			proof: &RangeProof{
   350  				StartProof: []ProofNode{{}},
   351  			},
   352  			expectedErr: ErrNoEndProof,
   353  		},
   354  		{
   355  			name:  "no end proof; has key-values",
   356  			start: maybe.Some([]byte{1}),
   357  			end:   maybe.Nothing[[]byte](),
   358  			proof: &RangeProof{
   359  				KeyValues: []KeyValue{{}},
   360  			},
   361  			expectedErr: ErrNoEndProof,
   362  		},
   363  		{
   364  			name:  "unsorted key values",
   365  			start: maybe.Some([]byte{1}),
   366  			end:   maybe.Nothing[[]byte](),
   367  			proof: &RangeProof{
   368  				KeyValues: []KeyValue{
   369  					{Key: []byte{1}, Value: []byte{1}},
   370  					{Key: []byte{0}, Value: []byte{0}},
   371  				},
   372  				EndProof: []ProofNode{{Key: Key{}}},
   373  			},
   374  			expectedErr: ErrNonIncreasingValues,
   375  		},
   376  		{
   377  			name:  "key lower than start",
   378  			start: maybe.Some([]byte{1}),
   379  			end:   maybe.Nothing[[]byte](),
   380  			proof: &RangeProof{
   381  				KeyValues: []KeyValue{
   382  					{Key: []byte{0}, Value: []byte{0}},
   383  				},
   384  				EndProof: []ProofNode{{Key: Key{}}},
   385  			},
   386  			expectedErr: ErrStateFromOutsideOfRange,
   387  		},
   388  		{
   389  			name:  "key greater than end",
   390  			start: maybe.Some([]byte{1}),
   391  			end:   maybe.Some([]byte{1}),
   392  			proof: &RangeProof{
   393  				KeyValues: []KeyValue{
   394  					{Key: []byte{2}, Value: []byte{0}},
   395  				},
   396  				EndProof: []ProofNode{{Key: Key{}}},
   397  			},
   398  			expectedErr: ErrStateFromOutsideOfRange,
   399  		},
   400  		{
   401  			name:  "start proof nodes in wrong order",
   402  			start: maybe.Some([]byte{1, 2}),
   403  			end:   maybe.Nothing[[]byte](),
   404  			proof: &RangeProof{
   405  				KeyValues: []KeyValue{
   406  					{Key: []byte{1, 2}, Value: []byte{1}},
   407  				},
   408  				StartProof: []ProofNode{
   409  					{
   410  						Key: ToKey([]byte{2}),
   411  					},
   412  					{
   413  						Key: ToKey([]byte{1}),
   414  					},
   415  				},
   416  				EndProof: []ProofNode{{Key: Key{}}},
   417  			},
   418  			expectedErr: ErrProofNodeNotForKey,
   419  		},
   420  		{
   421  			name:  "start proof has node for wrong key",
   422  			start: maybe.Some([]byte{1, 2}),
   423  			end:   maybe.Nothing[[]byte](),
   424  			proof: &RangeProof{
   425  				KeyValues: []KeyValue{
   426  					{Key: []byte{1, 2}, Value: []byte{1}},
   427  				},
   428  				StartProof: []ProofNode{
   429  					{
   430  						Key: ToKey([]byte{1}),
   431  					},
   432  					{
   433  						Key: ToKey([]byte{1, 2, 3}), // Not a prefix of [1, 2]
   434  					},
   435  					{
   436  						Key: ToKey([]byte{1, 2, 3, 4}),
   437  					},
   438  				},
   439  				EndProof: []ProofNode{{Key: Key{}}},
   440  			},
   441  			expectedErr: ErrProofNodeNotForKey,
   442  		},
   443  		{
   444  			name:  "end proof nodes in wrong order",
   445  			start: maybe.Nothing[[]byte](),
   446  			end:   maybe.Some([]byte{1, 2}),
   447  			proof: &RangeProof{
   448  				KeyValues: []KeyValue{
   449  					{Key: []byte{1, 2}, Value: []byte{1}},
   450  				},
   451  				EndProof: []ProofNode{
   452  					{
   453  						Key: ToKey([]byte{2}),
   454  					},
   455  					{
   456  						Key: ToKey([]byte{1}),
   457  					},
   458  				},
   459  			},
   460  			expectedErr: ErrProofNodeNotForKey,
   461  		},
   462  		{
   463  			name:  "end proof has node for wrong key",
   464  			start: maybe.Nothing[[]byte](),
   465  			end:   maybe.Some([]byte{1, 2}),
   466  			proof: &RangeProof{
   467  				KeyValues: []KeyValue{
   468  					{Key: []byte{1, 2}, Value: []byte{1}},
   469  				},
   470  				EndProof: []ProofNode{
   471  					{
   472  						Key: ToKey([]byte{1}),
   473  					},
   474  					{
   475  						Key: ToKey([]byte{1, 2, 3}), // Not a prefix of [1, 2]
   476  					},
   477  					{
   478  						Key: ToKey([]byte{1, 2, 3, 4}),
   479  					},
   480  				},
   481  			},
   482  			expectedErr: ErrProofNodeNotForKey,
   483  		},
   484  	}
   485  
   486  	for _, tt := range tests {
   487  		t.Run(tt.name, func(t *testing.T) {
   488  			err := tt.proof.Verify(context.Background(), tt.start, tt.end, ids.Empty, 4, DefaultHasher)
   489  			require.ErrorIs(t, err, tt.expectedErr)
   490  		})
   491  	}
   492  }
   493  
   494  func Test_RangeProof(t *testing.T) {
   495  	require := require.New(t)
   496  
   497  	db, err := getBasicDB()
   498  	require.NoError(err)
   499  	writeBasicBatch(t, db)
   500  
   501  	proof, err := db.GetRangeProof(context.Background(), maybe.Some([]byte{1}), maybe.Some([]byte{3, 5}), 10)
   502  	require.NoError(err)
   503  	require.NotNil(proof)
   504  	require.Len(proof.KeyValues, 3)
   505  
   506  	require.Equal([]byte{1}, proof.KeyValues[0].Key)
   507  	require.Equal([]byte{2}, proof.KeyValues[1].Key)
   508  	require.Equal([]byte{3}, proof.KeyValues[2].Key)
   509  
   510  	require.Equal([]byte{1}, proof.KeyValues[0].Value)
   511  	require.Equal([]byte{2}, proof.KeyValues[1].Value)
   512  	require.Equal([]byte{3}, proof.KeyValues[2].Value)
   513  
   514  	require.Len(proof.EndProof, 2)
   515  	require.Equal([]byte{0}, proof.EndProof[0].Key.Bytes())
   516  	require.Len(proof.EndProof[0].Children, 5) // 0,1,2,3,4
   517  	require.Equal([]byte{3}, proof.EndProof[1].Key.Bytes())
   518  
   519  	// only a single node here since others are duplicates in endproof
   520  	require.Equal([]byte{1}, proof.StartProof[0].Key.Bytes())
   521  
   522  	require.NoError(proof.Verify(
   523  		context.Background(),
   524  		maybe.Some([]byte{1}),
   525  		maybe.Some([]byte{3, 5}),
   526  		db.rootID,
   527  		db.tokenSize,
   528  		db.hasher,
   529  	))
   530  }
   531  
   532  func Test_RangeProof_BadBounds(t *testing.T) {
   533  	require := require.New(t)
   534  
   535  	db, err := getBasicDB()
   536  	require.NoError(err)
   537  
   538  	require.NoError(db.Put(nil, nil))
   539  
   540  	// non-nil start/end
   541  	proof, err := db.GetRangeProof(context.Background(), maybe.Some([]byte{4}), maybe.Some([]byte{3}), 50)
   542  	require.ErrorIs(err, ErrStartAfterEnd)
   543  	require.Nil(proof)
   544  }
   545  
   546  func Test_RangeProof_NilStart(t *testing.T) {
   547  	require := require.New(t)
   548  
   549  	db, err := getBasicDB()
   550  	require.NoError(err)
   551  	batch := db.NewBatch()
   552  	require.NoError(batch.Put([]byte("key1"), []byte("value1")))
   553  	require.NoError(batch.Put([]byte("key2"), []byte("value2")))
   554  	require.NoError(batch.Put([]byte("key3"), []byte("value3")))
   555  	require.NoError(batch.Put([]byte("key4"), []byte("value4")))
   556  	require.NoError(batch.Write())
   557  
   558  	val, err := db.Get([]byte("key1"))
   559  	require.NoError(err)
   560  	require.Equal([]byte("value1"), val)
   561  
   562  	proof, err := db.GetRangeProof(context.Background(), maybe.Nothing[[]byte](), maybe.Some([]byte("key35")), 2)
   563  	require.NoError(err)
   564  	require.NotNil(proof)
   565  
   566  	require.Len(proof.KeyValues, 2)
   567  
   568  	require.Equal([]byte("key1"), proof.KeyValues[0].Key)
   569  	require.Equal([]byte("key2"), proof.KeyValues[1].Key)
   570  
   571  	require.Equal([]byte("value1"), proof.KeyValues[0].Value)
   572  	require.Equal([]byte("value2"), proof.KeyValues[1].Value)
   573  
   574  	require.Equal(ToKey([]byte("key2")), proof.EndProof[1].Key, db.tokenSize)
   575  	require.Equal(ToKey([]byte("key2")).Take(28), proof.EndProof[0].Key)
   576  
   577  	require.NoError(proof.Verify(
   578  		context.Background(),
   579  		maybe.Nothing[[]byte](),
   580  		maybe.Some([]byte("key35")),
   581  		db.rootID,
   582  		db.tokenSize,
   583  		db.hasher,
   584  	))
   585  }
   586  
   587  func Test_RangeProof_NilEnd(t *testing.T) {
   588  	require := require.New(t)
   589  
   590  	db, err := getBasicDB()
   591  	require.NoError(err)
   592  
   593  	writeBasicBatch(t, db)
   594  	require.NoError(err)
   595  
   596  	proof, err := db.GetRangeProof( // Should have keys [1], [2]
   597  		context.Background(),
   598  		maybe.Some([]byte{1}),
   599  		maybe.Nothing[[]byte](),
   600  		2,
   601  	)
   602  	require.NoError(err)
   603  	require.NotNil(proof)
   604  
   605  	require.Len(proof.KeyValues, 2)
   606  
   607  	require.Equal([]byte{1}, proof.KeyValues[0].Key)
   608  	require.Equal([]byte{2}, proof.KeyValues[1].Key)
   609  
   610  	require.Equal([]byte{1}, proof.KeyValues[0].Value)
   611  	require.Equal([]byte{2}, proof.KeyValues[1].Value)
   612  
   613  	require.Equal([]byte{1}, proof.StartProof[0].Key.Bytes())
   614  
   615  	require.Equal(db.root.Value().key, proof.EndProof[0].Key)
   616  	require.Equal([]byte{2}, proof.EndProof[1].Key.Bytes())
   617  
   618  	require.NoError(proof.Verify(
   619  		context.Background(),
   620  		maybe.Some([]byte{1}),
   621  		maybe.Nothing[[]byte](),
   622  		db.rootID,
   623  		db.tokenSize,
   624  		db.hasher,
   625  	))
   626  }
   627  
   628  func Test_RangeProof_EmptyValues(t *testing.T) {
   629  	require := require.New(t)
   630  
   631  	db, err := getBasicDB()
   632  	require.NoError(err)
   633  	batch := db.NewBatch()
   634  	require.NoError(batch.Put([]byte("key1"), nil))
   635  	require.NoError(batch.Put([]byte("key12"), []byte("value1")))
   636  	require.NoError(batch.Put([]byte("key2"), []byte{}))
   637  	require.NoError(batch.Write())
   638  
   639  	val, err := db.Get([]byte("key12"))
   640  	require.NoError(err)
   641  	require.Equal([]byte("value1"), val)
   642  
   643  	proof, err := db.GetRangeProof(context.Background(), maybe.Some([]byte("key1")), maybe.Some([]byte("key2")), 10)
   644  	require.NoError(err)
   645  	require.NotNil(proof)
   646  
   647  	require.Len(proof.KeyValues, 3)
   648  	require.Equal([]byte("key1"), proof.KeyValues[0].Key)
   649  	require.Empty(proof.KeyValues[0].Value)
   650  	require.Equal([]byte("key12"), proof.KeyValues[1].Key)
   651  	require.Equal([]byte("value1"), proof.KeyValues[1].Value)
   652  	require.Equal([]byte("key2"), proof.KeyValues[2].Key)
   653  	require.Empty(proof.KeyValues[2].Value)
   654  
   655  	require.Len(proof.StartProof, 1)
   656  	require.Equal(ToKey([]byte("key1")), proof.StartProof[0].Key)
   657  
   658  	require.Len(proof.EndProof, 2)
   659  	require.Equal(ToKey([]byte("key1")).Take(28), proof.EndProof[0].Key, db.tokenSize) // root
   660  	require.Equal(ToKey([]byte("key2")), proof.EndProof[1].Key, db.tokenSize)
   661  
   662  	require.NoError(proof.Verify(
   663  		context.Background(),
   664  		maybe.Some([]byte("key1")),
   665  		maybe.Some([]byte("key2")),
   666  		db.rootID,
   667  		db.tokenSize,
   668  		db.hasher,
   669  	))
   670  }
   671  
   672  func Test_ChangeProof_Missing_History_For_EndRoot(t *testing.T) {
   673  	require := require.New(t)
   674  	seed := time.Now().UnixNano()
   675  	t.Logf("Seed: %d", seed)
   676  	rand := rand.New(rand.NewSource(seed)) // #nosec G404
   677  
   678  	db, err := getBasicDB()
   679  	require.NoError(err)
   680  
   681  	roots := []ids.ID{}
   682  	for i := 0; i < defaultHistoryLength+1; i++ {
   683  		key := make([]byte, 16)
   684  		_, _ = rand.Read(key)
   685  		require.NoError(db.Put(key, nil))
   686  		root, err := db.GetMerkleRoot(context.Background())
   687  		require.NoError(err)
   688  		roots = append(roots, root)
   689  	}
   690  
   691  	_, err = db.GetChangeProof(
   692  		context.Background(),
   693  		roots[len(roots)-1],
   694  		ids.GenerateTestID(),
   695  		maybe.Nothing[[]byte](),
   696  		maybe.Nothing[[]byte](),
   697  		50,
   698  	)
   699  	require.ErrorIs(err, ErrNoEndRoot)
   700  	require.ErrorIs(err, ErrInsufficientHistory)
   701  
   702  	_, err = db.GetChangeProof(
   703  		context.Background(),
   704  		roots[0],
   705  		roots[len(roots)-1],
   706  		maybe.Nothing[[]byte](),
   707  		maybe.Nothing[[]byte](),
   708  		50,
   709  	)
   710  	require.NotErrorIs(err, ErrNoEndRoot)
   711  	require.ErrorIs(err, ErrInsufficientHistory)
   712  
   713  	_, err = db.GetChangeProof(
   714  		context.Background(),
   715  		roots[1],
   716  		roots[len(roots)-1],
   717  		maybe.Nothing[[]byte](),
   718  		maybe.Nothing[[]byte](),
   719  		50,
   720  	)
   721  	require.NoError(err)
   722  }
   723  
   724  func Test_ChangeProof_BadBounds(t *testing.T) {
   725  	require := require.New(t)
   726  
   727  	db, err := getBasicDB()
   728  	require.NoError(err)
   729  
   730  	startRoot, err := db.GetMerkleRoot(context.Background())
   731  	require.NoError(err)
   732  
   733  	require.NoError(db.PutContext(context.Background(), []byte{0}, []byte{0}))
   734  
   735  	endRoot, err := db.GetMerkleRoot(context.Background())
   736  	require.NoError(err)
   737  
   738  	// non-nil start/end
   739  	proof, err := db.GetChangeProof(context.Background(), startRoot, endRoot, maybe.Some([]byte("key4")), maybe.Some([]byte("key3")), 50)
   740  	require.ErrorIs(err, ErrStartAfterEnd)
   741  	require.Nil(proof)
   742  }
   743  
   744  func Test_ChangeProof_Verify(t *testing.T) {
   745  	require := require.New(t)
   746  
   747  	db, err := getBasicDB()
   748  	require.NoError(err)
   749  	batch := db.NewBatch()
   750  	require.NoError(batch.Put([]byte("key20"), []byte("value0")))
   751  	require.NoError(batch.Put([]byte("key21"), []byte("value1")))
   752  	require.NoError(batch.Put([]byte("key22"), []byte("value2")))
   753  	require.NoError(batch.Put([]byte("key23"), []byte("value3")))
   754  	require.NoError(batch.Put([]byte("key24"), []byte("value4")))
   755  	require.NoError(batch.Write())
   756  	startRoot, err := db.GetMerkleRoot(context.Background())
   757  	require.NoError(err)
   758  
   759  	// create a second db that has "synced" to the start root
   760  	dbClone, err := getBasicDB()
   761  	require.NoError(err)
   762  	batch = dbClone.NewBatch()
   763  	require.NoError(batch.Put([]byte("key20"), []byte("value0")))
   764  	require.NoError(batch.Put([]byte("key21"), []byte("value1")))
   765  	require.NoError(batch.Put([]byte("key22"), []byte("value2")))
   766  	require.NoError(batch.Put([]byte("key23"), []byte("value3")))
   767  	require.NoError(batch.Put([]byte("key24"), []byte("value4")))
   768  	require.NoError(batch.Write())
   769  
   770  	// the second db has started to sync some of the range outside of the range proof
   771  	batch = dbClone.NewBatch()
   772  	require.NoError(batch.Put([]byte("key31"), []byte("value1")))
   773  	require.NoError(batch.Write())
   774  
   775  	batch = db.NewBatch()
   776  	require.NoError(batch.Put([]byte("key25"), []byte("value0")))
   777  	require.NoError(batch.Put([]byte("key26"), []byte("value1")))
   778  	require.NoError(batch.Put([]byte("key27"), []byte("value2")))
   779  	require.NoError(batch.Put([]byte("key28"), []byte("value3")))
   780  	require.NoError(batch.Put([]byte("key29"), []byte("value4")))
   781  	require.NoError(batch.Write())
   782  
   783  	batch = db.NewBatch()
   784  	require.NoError(batch.Put([]byte("key30"), []byte("value0")))
   785  	require.NoError(batch.Put([]byte("key31"), []byte("value1")))
   786  	require.NoError(batch.Put([]byte("key32"), []byte("value2")))
   787  	require.NoError(batch.Delete([]byte("key21")))
   788  	require.NoError(batch.Delete([]byte("key22")))
   789  	require.NoError(batch.Write())
   790  
   791  	endRoot, err := db.GetMerkleRoot(context.Background())
   792  	require.NoError(err)
   793  
   794  	// non-nil start/end
   795  	proof, err := db.GetChangeProof(context.Background(), startRoot, endRoot, maybe.Some([]byte("key21")), maybe.Some([]byte("key30")), 50)
   796  	require.NoError(err)
   797  	require.NotNil(proof)
   798  
   799  	require.NoError(dbClone.VerifyChangeProof(context.Background(), proof, maybe.Some([]byte("key21")), maybe.Some([]byte("key30")), db.getMerkleRoot()))
   800  
   801  	// low maxLength
   802  	proof, err = db.GetChangeProof(context.Background(), startRoot, endRoot, maybe.Nothing[[]byte](), maybe.Nothing[[]byte](), 5)
   803  	require.NoError(err)
   804  	require.NotNil(proof)
   805  
   806  	require.NoError(dbClone.VerifyChangeProof(context.Background(), proof, maybe.Nothing[[]byte](), maybe.Nothing[[]byte](), db.getMerkleRoot()))
   807  
   808  	// nil start/end
   809  	proof, err = db.GetChangeProof(context.Background(), startRoot, endRoot, maybe.Nothing[[]byte](), maybe.Nothing[[]byte](), 50)
   810  	require.NoError(err)
   811  	require.NotNil(proof)
   812  
   813  	require.NoError(dbClone.VerifyChangeProof(context.Background(), proof, maybe.Nothing[[]byte](), maybe.Nothing[[]byte](), endRoot))
   814  	require.NoError(dbClone.CommitChangeProof(context.Background(), proof))
   815  
   816  	newRoot, err := dbClone.GetMerkleRoot(context.Background())
   817  	require.NoError(err)
   818  	require.Equal(endRoot, newRoot)
   819  
   820  	proof, err = db.GetChangeProof(context.Background(), startRoot, endRoot, maybe.Some([]byte("key20")), maybe.Some([]byte("key30")), 50)
   821  	require.NoError(err)
   822  	require.NotNil(proof)
   823  
   824  	require.NoError(dbClone.VerifyChangeProof(context.Background(), proof, maybe.Some([]byte("key20")), maybe.Some([]byte("key30")), db.getMerkleRoot()))
   825  }
   826  
   827  func Test_ChangeProof_Verify_Bad_Data(t *testing.T) {
   828  	type test struct {
   829  		name        string
   830  		malform     func(proof *ChangeProof)
   831  		expectedErr error
   832  	}
   833  
   834  	tests := []test{
   835  		{
   836  			name:        "happyPath",
   837  			malform:     func(*ChangeProof) {},
   838  			expectedErr: nil,
   839  		},
   840  		{
   841  			name: "odd length key path with value",
   842  			malform: func(proof *ChangeProof) {
   843  				proof.EndProof[0].ValueOrHash = maybe.Some([]byte{1, 2})
   844  			},
   845  			expectedErr: ErrPartialByteLengthWithValue,
   846  		},
   847  		{
   848  			name: "last proof node has missing value",
   849  			malform: func(proof *ChangeProof) {
   850  				proof.EndProof[len(proof.EndProof)-1].ValueOrHash = maybe.Nothing[[]byte]()
   851  			},
   852  			expectedErr: ErrProofValueDoesntMatch,
   853  		},
   854  		{
   855  			name: "missing key/value",
   856  			malform: func(proof *ChangeProof) {
   857  				proof.KeyChanges = proof.KeyChanges[1:]
   858  			},
   859  			expectedErr: ErrProofValueDoesntMatch,
   860  		},
   861  	}
   862  
   863  	for _, tt := range tests {
   864  		t.Run(tt.name, func(t *testing.T) {
   865  			require := require.New(t)
   866  
   867  			db, err := getBasicDB()
   868  			require.NoError(err)
   869  
   870  			startRoot, err := db.GetMerkleRoot(context.Background())
   871  			require.NoError(err)
   872  
   873  			writeBasicBatch(t, db)
   874  
   875  			endRoot, err := db.GetMerkleRoot(context.Background())
   876  			require.NoError(err)
   877  
   878  			// create a second db that will be synced to the first db
   879  			dbClone, err := getBasicDB()
   880  			require.NoError(err)
   881  
   882  			proof, err := db.GetChangeProof(
   883  				context.Background(),
   884  				startRoot,
   885  				endRoot,
   886  				maybe.Some([]byte{2}),
   887  				maybe.Some([]byte{3, 0}),
   888  				50,
   889  			)
   890  			require.NoError(err)
   891  			require.NotNil(proof)
   892  
   893  			tt.malform(proof)
   894  
   895  			err = dbClone.VerifyChangeProof(
   896  				context.Background(),
   897  				proof,
   898  				maybe.Some([]byte{2}),
   899  				maybe.Some([]byte{3, 0}),
   900  				db.getMerkleRoot(),
   901  			)
   902  			require.ErrorIs(err, tt.expectedErr)
   903  		})
   904  	}
   905  }
   906  
   907  func Test_ChangeProof_Syntactic_Verify(t *testing.T) {
   908  	type test struct {
   909  		name        string
   910  		proof       *ChangeProof
   911  		start       maybe.Maybe[[]byte]
   912  		end         maybe.Maybe[[]byte]
   913  		expectedErr error
   914  	}
   915  
   916  	tests := []test{
   917  		{
   918  			name:        "start after end",
   919  			proof:       nil,
   920  			start:       maybe.Some([]byte{1}),
   921  			end:         maybe.Some([]byte{0}),
   922  			expectedErr: ErrStartAfterEnd,
   923  		},
   924  		{
   925  			name:        "empty",
   926  			proof:       &ChangeProof{},
   927  			start:       maybe.Nothing[[]byte](),
   928  			end:         maybe.Nothing[[]byte](),
   929  			expectedErr: ErrEmptyProof,
   930  		},
   931  		{
   932  			name: "no end proof",
   933  			proof: &ChangeProof{
   934  				StartProof: []ProofNode{{}},
   935  			},
   936  			start:       maybe.Nothing[[]byte](),
   937  			end:         maybe.Some([]byte{1}),
   938  			expectedErr: ErrNoEndProof,
   939  		},
   940  		{
   941  			name: "no start proof",
   942  			proof: &ChangeProof{
   943  				KeyChanges: []KeyChange{{Key: []byte{1}}},
   944  			},
   945  			start:       maybe.Some([]byte{1}),
   946  			end:         maybe.Nothing[[]byte](),
   947  			expectedErr: ErrNoStartProof,
   948  		},
   949  		{
   950  			name: "non-increasing key-values",
   951  			proof: &ChangeProof{
   952  				KeyChanges: []KeyChange{
   953  					{Key: []byte{1}},
   954  					{Key: []byte{0}},
   955  				},
   956  			},
   957  			start:       maybe.Nothing[[]byte](),
   958  			end:         maybe.Nothing[[]byte](),
   959  			expectedErr: ErrNonIncreasingValues,
   960  		},
   961  		{
   962  			name: "key-value too low",
   963  			proof: &ChangeProof{
   964  				StartProof: []ProofNode{{}},
   965  				KeyChanges: []KeyChange{
   966  					{Key: []byte{0}},
   967  				},
   968  			},
   969  			start:       maybe.Some([]byte{1}),
   970  			end:         maybe.Nothing[[]byte](),
   971  			expectedErr: ErrStateFromOutsideOfRange,
   972  		},
   973  		{
   974  			name: "key-value too great",
   975  			proof: &ChangeProof{
   976  				EndProof: []ProofNode{{}},
   977  				KeyChanges: []KeyChange{
   978  					{Key: []byte{2}},
   979  				},
   980  			},
   981  			start:       maybe.Nothing[[]byte](),
   982  			end:         maybe.Some([]byte{1}),
   983  			expectedErr: ErrStateFromOutsideOfRange,
   984  		},
   985  		{
   986  			name: "duplicate key",
   987  			proof: &ChangeProof{
   988  				KeyChanges: []KeyChange{
   989  					{Key: []byte{1}},
   990  					{Key: []byte{1}},
   991  				},
   992  			},
   993  			start:       maybe.Nothing[[]byte](),
   994  			end:         maybe.Nothing[[]byte](),
   995  			expectedErr: ErrNonIncreasingValues,
   996  		},
   997  		{
   998  			name: "start proof node has wrong prefix",
   999  			proof: &ChangeProof{
  1000  				StartProof: []ProofNode{
  1001  					{Key: ToKey([]byte{2})},
  1002  					{Key: ToKey([]byte{2, 3})},
  1003  				},
  1004  			},
  1005  			start:       maybe.Some([]byte{1, 2, 3}),
  1006  			end:         maybe.Nothing[[]byte](),
  1007  			expectedErr: ErrProofNodeNotForKey,
  1008  		},
  1009  		{
  1010  			name: "start proof non-increasing",
  1011  			proof: &ChangeProof{
  1012  				StartProof: []ProofNode{
  1013  					{Key: ToKey([]byte{1})},
  1014  					{Key: ToKey([]byte{2, 3})},
  1015  				},
  1016  			},
  1017  			start:       maybe.Some([]byte{1, 2, 3}),
  1018  			end:         maybe.Nothing[[]byte](),
  1019  			expectedErr: ErrNonIncreasingProofNodes,
  1020  		},
  1021  		{
  1022  			name: "end proof node has wrong prefix",
  1023  			proof: &ChangeProof{
  1024  				KeyChanges: []KeyChange{
  1025  					{Key: []byte{1, 2}, Value: maybe.Some([]byte{0})},
  1026  				},
  1027  				EndProof: []ProofNode{
  1028  					{Key: ToKey([]byte{2})},
  1029  					{Key: ToKey([]byte{2, 3})},
  1030  				},
  1031  			},
  1032  			start:       maybe.Nothing[[]byte](),
  1033  			end:         maybe.Nothing[[]byte](),
  1034  			expectedErr: ErrProofNodeNotForKey,
  1035  		},
  1036  		{
  1037  			name: "end proof non-increasing",
  1038  			proof: &ChangeProof{
  1039  				KeyChanges: []KeyChange{
  1040  					{Key: []byte{1, 2, 3}},
  1041  				},
  1042  				EndProof: []ProofNode{
  1043  					{Key: ToKey([]byte{1})},
  1044  					{Key: ToKey([]byte{2, 3})},
  1045  				},
  1046  			},
  1047  			start:       maybe.Nothing[[]byte](),
  1048  			end:         maybe.Nothing[[]byte](),
  1049  			expectedErr: ErrNonIncreasingProofNodes,
  1050  		},
  1051  	}
  1052  
  1053  	for _, tt := range tests {
  1054  		t.Run(tt.name, func(t *testing.T) {
  1055  			require := require.New(t)
  1056  
  1057  			db, err := getBasicDB()
  1058  			require.NoError(err)
  1059  			err = db.VerifyChangeProof(context.Background(), tt.proof, tt.start, tt.end, ids.Empty)
  1060  			require.ErrorIs(err, tt.expectedErr)
  1061  		})
  1062  	}
  1063  }
  1064  
  1065  func TestVerifyKeyValues(t *testing.T) {
  1066  	type test struct {
  1067  		name        string
  1068  		start       maybe.Maybe[[]byte]
  1069  		end         maybe.Maybe[[]byte]
  1070  		kvs         []KeyValue
  1071  		expectedErr error
  1072  	}
  1073  
  1074  	tests := []test{
  1075  		{
  1076  			name:        "empty",
  1077  			start:       maybe.Nothing[[]byte](),
  1078  			end:         maybe.Nothing[[]byte](),
  1079  			kvs:         nil,
  1080  			expectedErr: nil,
  1081  		},
  1082  		{
  1083  			name:  "1 key",
  1084  			start: maybe.Nothing[[]byte](),
  1085  			end:   maybe.Nothing[[]byte](),
  1086  			kvs: []KeyValue{
  1087  				{Key: []byte{0}},
  1088  			},
  1089  			expectedErr: nil,
  1090  		},
  1091  		{
  1092  			name:  "non-increasing keys",
  1093  			start: maybe.Nothing[[]byte](),
  1094  			end:   maybe.Nothing[[]byte](),
  1095  			kvs: []KeyValue{
  1096  				{Key: []byte{0}},
  1097  				{Key: []byte{0}},
  1098  			},
  1099  			expectedErr: ErrNonIncreasingValues,
  1100  		},
  1101  		{
  1102  			name:  "key before start",
  1103  			start: maybe.Some([]byte{1, 2}),
  1104  			end:   maybe.Nothing[[]byte](),
  1105  			kvs: []KeyValue{
  1106  				{Key: []byte{1}},
  1107  				{Key: []byte{1, 2}},
  1108  			},
  1109  			expectedErr: ErrStateFromOutsideOfRange,
  1110  		},
  1111  		{
  1112  			name:  "key after end",
  1113  			start: maybe.Nothing[[]byte](),
  1114  			end:   maybe.Some([]byte{1, 2}),
  1115  			kvs: []KeyValue{
  1116  				{Key: []byte{1}},
  1117  				{Key: []byte{1, 2}},
  1118  				{Key: []byte{1, 2, 3}},
  1119  			},
  1120  			expectedErr: ErrStateFromOutsideOfRange,
  1121  		},
  1122  		{
  1123  			name:  "happy path",
  1124  			start: maybe.Nothing[[]byte](),
  1125  			end:   maybe.Some([]byte{1, 2, 3}),
  1126  			kvs: []KeyValue{
  1127  				{Key: []byte{1}},
  1128  				{Key: []byte{1, 2}},
  1129  			},
  1130  			expectedErr: nil,
  1131  		},
  1132  	}
  1133  
  1134  	for _, tt := range tests {
  1135  		t.Run(tt.name, func(t *testing.T) {
  1136  			err := verifyKeyValues(tt.kvs, tt.start, tt.end)
  1137  			require.ErrorIs(t, err, tt.expectedErr)
  1138  		})
  1139  	}
  1140  }
  1141  
  1142  func TestVerifyProofPath(t *testing.T) {
  1143  	type test struct {
  1144  		name        string
  1145  		path        []ProofNode
  1146  		proofKey    maybe.Maybe[Key]
  1147  		expectedErr error
  1148  	}
  1149  
  1150  	tests := []test{
  1151  		{
  1152  			name:        "empty",
  1153  			path:        nil,
  1154  			proofKey:    maybe.Nothing[Key](),
  1155  			expectedErr: nil,
  1156  		},
  1157  		{
  1158  			name:        "1 element",
  1159  			path:        []ProofNode{{Key: ToKey([]byte{1})}},
  1160  			proofKey:    maybe.Nothing[Key](),
  1161  			expectedErr: nil,
  1162  		},
  1163  		{
  1164  			name: "non-increasing keys",
  1165  			path: []ProofNode{
  1166  				{Key: ToKey([]byte{1})},
  1167  				{Key: ToKey([]byte{1, 2})},
  1168  				{Key: ToKey([]byte{1, 3})},
  1169  			},
  1170  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1171  			expectedErr: ErrNonIncreasingProofNodes,
  1172  		},
  1173  		{
  1174  			name: "invalid key",
  1175  			path: []ProofNode{
  1176  				{Key: ToKey([]byte{1})},
  1177  				{Key: ToKey([]byte{1, 2})},
  1178  				{Key: ToKey([]byte{1, 2, 4})},
  1179  				{Key: ToKey([]byte{1, 2, 3})},
  1180  			},
  1181  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1182  			expectedErr: ErrProofNodeNotForKey,
  1183  		},
  1184  		{
  1185  			name: "extra node inclusion proof",
  1186  			path: []ProofNode{
  1187  				{Key: ToKey([]byte{1})},
  1188  				{Key: ToKey([]byte{1, 2})},
  1189  				{Key: ToKey([]byte{1, 2, 3})},
  1190  			},
  1191  			proofKey:    maybe.Some(ToKey([]byte{1, 2})),
  1192  			expectedErr: ErrProofNodeNotForKey,
  1193  		},
  1194  		{
  1195  			name: "extra node exclusion proof",
  1196  			path: []ProofNode{
  1197  				{Key: ToKey([]byte{1})},
  1198  				{Key: ToKey([]byte{1, 3})},
  1199  				{Key: ToKey([]byte{1, 3, 4})},
  1200  			},
  1201  			proofKey:    maybe.Some(ToKey([]byte{1, 2})),
  1202  			expectedErr: ErrProofNodeNotForKey,
  1203  		},
  1204  		{
  1205  			name: "happy path exclusion proof",
  1206  			path: []ProofNode{
  1207  				{Key: ToKey([]byte{1})},
  1208  				{Key: ToKey([]byte{1, 2})},
  1209  				{Key: ToKey([]byte{1, 2, 4})},
  1210  			},
  1211  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1212  			expectedErr: nil,
  1213  		},
  1214  		{
  1215  			name: "happy path inclusion proof",
  1216  			path: []ProofNode{
  1217  				{Key: ToKey([]byte{1})},
  1218  				{Key: ToKey([]byte{1, 2})},
  1219  				{Key: ToKey([]byte{1, 2, 3})},
  1220  			},
  1221  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1222  			expectedErr: nil,
  1223  		},
  1224  		{
  1225  			name: "repeat nodes",
  1226  			path: []ProofNode{
  1227  				{Key: ToKey([]byte{1})},
  1228  				{Key: ToKey([]byte{1})},
  1229  				{Key: ToKey([]byte{1, 2})},
  1230  				{Key: ToKey([]byte{1, 2, 3})},
  1231  			},
  1232  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1233  			expectedErr: ErrNonIncreasingProofNodes,
  1234  		},
  1235  		{
  1236  			name: "repeat nodes 2",
  1237  			path: []ProofNode{
  1238  				{Key: ToKey([]byte{1})},
  1239  				{Key: ToKey([]byte{1, 2})},
  1240  				{Key: ToKey([]byte{1, 2})},
  1241  				{Key: ToKey([]byte{1, 2, 3})},
  1242  			},
  1243  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1244  			expectedErr: ErrNonIncreasingProofNodes,
  1245  		},
  1246  		{
  1247  			name: "repeat nodes 3",
  1248  			path: []ProofNode{
  1249  				{Key: ToKey([]byte{1})},
  1250  				{Key: ToKey([]byte{1, 2})},
  1251  				{Key: ToKey([]byte{1, 2, 3})},
  1252  				{Key: ToKey([]byte{1, 2, 3})},
  1253  			},
  1254  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1255  			expectedErr: ErrProofNodeNotForKey,
  1256  		},
  1257  		{
  1258  			name: "oddLength key with value",
  1259  			path: []ProofNode{
  1260  				{Key: ToKey([]byte{1})},
  1261  				{Key: ToKey([]byte{1, 2})},
  1262  				{
  1263  					Key: Key{
  1264  						value:  string([]byte{1, 2, 240}),
  1265  						length: 20,
  1266  					},
  1267  					ValueOrHash: maybe.Some([]byte{1}),
  1268  				},
  1269  			},
  1270  			proofKey:    maybe.Some(ToKey([]byte{1, 2, 3})),
  1271  			expectedErr: ErrPartialByteLengthWithValue,
  1272  		},
  1273  	}
  1274  
  1275  	for _, tt := range tests {
  1276  		t.Run(tt.name, func(t *testing.T) {
  1277  			err := verifyProofPath(tt.path, tt.proofKey)
  1278  			require.ErrorIs(t, err, tt.expectedErr)
  1279  		})
  1280  	}
  1281  }
  1282  
  1283  func TestProofNodeUnmarshalProtoInvalidMaybe(t *testing.T) {
  1284  	now := time.Now().UnixNano()
  1285  	t.Logf("seed: %d", now)
  1286  	rand := rand.New(rand.NewSource(now)) // #nosec G404
  1287  
  1288  	node := newRandomProofNode(rand)
  1289  	protoNode := node.ToProto()
  1290  
  1291  	// It's invalid to have a value and be nothing.
  1292  	protoNode.ValueOrHash = &pb.MaybeBytes{
  1293  		Value:     []byte{1, 2, 3},
  1294  		IsNothing: true,
  1295  	}
  1296  
  1297  	var unmarshaledNode ProofNode
  1298  	err := unmarshaledNode.UnmarshalProto(protoNode)
  1299  	require.ErrorIs(t, err, ErrInvalidMaybe)
  1300  }
  1301  
  1302  func TestProofNodeUnmarshalProtoInvalidChildBytes(t *testing.T) {
  1303  	now := time.Now().UnixNano()
  1304  	t.Logf("seed: %d", now)
  1305  	rand := rand.New(rand.NewSource(now)) // #nosec G404
  1306  
  1307  	node := newRandomProofNode(rand)
  1308  	protoNode := node.ToProto()
  1309  
  1310  	protoNode.Children = map[uint32][]byte{
  1311  		1: []byte("not 32 bytes"),
  1312  	}
  1313  
  1314  	var unmarshaledNode ProofNode
  1315  	err := unmarshaledNode.UnmarshalProto(protoNode)
  1316  	require.ErrorIs(t, err, hashing.ErrInvalidHashLen)
  1317  }
  1318  
  1319  func TestProofNodeUnmarshalProtoInvalidChildIndex(t *testing.T) {
  1320  	now := time.Now().UnixNano()
  1321  	t.Logf("seed: %d", now)
  1322  	rand := rand.New(rand.NewSource(now)) // #nosec G404
  1323  
  1324  	node := newRandomProofNode(rand)
  1325  	protoNode := node.ToProto()
  1326  
  1327  	childID := ids.GenerateTestID()
  1328  	protoNode.Children[256] = childID[:]
  1329  
  1330  	var unmarshaledNode ProofNode
  1331  	err := unmarshaledNode.UnmarshalProto(protoNode)
  1332  	require.ErrorIs(t, err, errChildIndexTooLarge)
  1333  }
  1334  
  1335  func TestProofNodeUnmarshalProtoMissingFields(t *testing.T) {
  1336  	now := time.Now().UnixNano()
  1337  	t.Logf("seed: %d", now)
  1338  	rand := rand.New(rand.NewSource(now)) // #nosec G404
  1339  
  1340  	type test struct {
  1341  		name        string
  1342  		nodeFunc    func() *pb.ProofNode
  1343  		expectedErr error
  1344  	}
  1345  
  1346  	tests := []test{
  1347  		{
  1348  			name: "nil node",
  1349  			nodeFunc: func() *pb.ProofNode {
  1350  				return nil
  1351  			},
  1352  			expectedErr: ErrNilProofNode,
  1353  		},
  1354  		{
  1355  			name: "nil ValueOrHash",
  1356  			nodeFunc: func() *pb.ProofNode {
  1357  				node := newRandomProofNode(rand)
  1358  				protoNode := node.ToProto()
  1359  				protoNode.ValueOrHash = nil
  1360  				return protoNode
  1361  			},
  1362  			expectedErr: ErrNilValueOrHash,
  1363  		},
  1364  		{
  1365  			name: "nil key",
  1366  			nodeFunc: func() *pb.ProofNode {
  1367  				node := newRandomProofNode(rand)
  1368  				protoNode := node.ToProto()
  1369  				protoNode.Key = nil
  1370  				return protoNode
  1371  			},
  1372  			expectedErr: ErrNilKey,
  1373  		},
  1374  	}
  1375  
  1376  	for _, tt := range tests {
  1377  		t.Run(tt.name, func(t *testing.T) {
  1378  			var node ProofNode
  1379  			err := node.UnmarshalProto(tt.nodeFunc())
  1380  			require.ErrorIs(t, err, tt.expectedErr)
  1381  		})
  1382  	}
  1383  }
  1384  
  1385  func FuzzProofNodeProtoMarshalUnmarshal(f *testing.F) {
  1386  	f.Fuzz(func(
  1387  		t *testing.T,
  1388  		randSeed int64,
  1389  	) {
  1390  		require := require.New(t)
  1391  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1392  		node := newRandomProofNode(rand)
  1393  
  1394  		// Marshal and unmarshal it.
  1395  		// Assert the unmarshaled one is the same as the original.
  1396  		protoNode := node.ToProto()
  1397  		var unmarshaledNode ProofNode
  1398  		require.NoError(unmarshaledNode.UnmarshalProto(protoNode))
  1399  		require.Equal(node, unmarshaledNode)
  1400  
  1401  		// Marshaling again should yield same result.
  1402  		protoUnmarshaledNode := unmarshaledNode.ToProto()
  1403  		require.Equal(protoNode, protoUnmarshaledNode)
  1404  	})
  1405  }
  1406  
  1407  func FuzzRangeProofProtoMarshalUnmarshal(f *testing.F) {
  1408  	f.Fuzz(func(
  1409  		t *testing.T,
  1410  		randSeed int64,
  1411  	) {
  1412  		require := require.New(t)
  1413  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1414  
  1415  		// Make a random range proof.
  1416  		startProofLen := rand.Intn(32)
  1417  		startProof := make([]ProofNode, startProofLen)
  1418  		for i := 0; i < startProofLen; i++ {
  1419  			startProof[i] = newRandomProofNode(rand)
  1420  		}
  1421  
  1422  		endProofLen := rand.Intn(32)
  1423  		endProof := make([]ProofNode, endProofLen)
  1424  		for i := 0; i < endProofLen; i++ {
  1425  			endProof[i] = newRandomProofNode(rand)
  1426  		}
  1427  
  1428  		numKeyValues := rand.Intn(128)
  1429  		keyValues := make([]KeyValue, numKeyValues)
  1430  		for i := 0; i < numKeyValues; i++ {
  1431  			keyLen := rand.Intn(32)
  1432  			key := make([]byte, keyLen)
  1433  			_, _ = rand.Read(key)
  1434  
  1435  			valueLen := rand.Intn(32)
  1436  			value := make([]byte, valueLen)
  1437  			_, _ = rand.Read(value)
  1438  
  1439  			keyValues[i] = KeyValue{
  1440  				Key:   key,
  1441  				Value: value,
  1442  			}
  1443  		}
  1444  
  1445  		proof := RangeProof{
  1446  			StartProof: startProof,
  1447  			EndProof:   endProof,
  1448  			KeyValues:  keyValues,
  1449  		}
  1450  
  1451  		// Marshal and unmarshal it.
  1452  		// Assert the unmarshaled one is the same as the original.
  1453  		var unmarshaledProof RangeProof
  1454  		protoProof := proof.ToProto()
  1455  		require.NoError(unmarshaledProof.UnmarshalProto(protoProof))
  1456  		require.Equal(proof, unmarshaledProof)
  1457  
  1458  		// Marshaling again should yield same result.
  1459  		protoUnmarshaledProof := unmarshaledProof.ToProto()
  1460  		require.Equal(protoProof, protoUnmarshaledProof)
  1461  	})
  1462  }
  1463  
  1464  func FuzzChangeProofProtoMarshalUnmarshal(f *testing.F) {
  1465  	f.Fuzz(func(
  1466  		t *testing.T,
  1467  		randSeed int64,
  1468  	) {
  1469  		require := require.New(t)
  1470  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1471  
  1472  		// Make a random change proof.
  1473  		startProofLen := rand.Intn(32)
  1474  		startProof := make([]ProofNode, startProofLen)
  1475  		for i := 0; i < startProofLen; i++ {
  1476  			startProof[i] = newRandomProofNode(rand)
  1477  		}
  1478  
  1479  		endProofLen := rand.Intn(32)
  1480  		endProof := make([]ProofNode, endProofLen)
  1481  		for i := 0; i < endProofLen; i++ {
  1482  			endProof[i] = newRandomProofNode(rand)
  1483  		}
  1484  
  1485  		numKeyChanges := rand.Intn(128)
  1486  		keyChanges := make([]KeyChange, numKeyChanges)
  1487  		for i := 0; i < numKeyChanges; i++ {
  1488  			keyLen := rand.Intn(32)
  1489  			key := make([]byte, keyLen)
  1490  			_, _ = rand.Read(key)
  1491  
  1492  			value := maybe.Nothing[[]byte]()
  1493  			hasValue := rand.Intn(2) == 0
  1494  			if hasValue {
  1495  				valueLen := rand.Intn(32)
  1496  				valueBytes := make([]byte, valueLen)
  1497  				_, _ = rand.Read(valueBytes)
  1498  				value = maybe.Some(valueBytes)
  1499  			}
  1500  
  1501  			keyChanges[i] = KeyChange{
  1502  				Key:   key,
  1503  				Value: value,
  1504  			}
  1505  		}
  1506  
  1507  		proof := ChangeProof{
  1508  			StartProof: startProof,
  1509  			EndProof:   endProof,
  1510  			KeyChanges: keyChanges,
  1511  		}
  1512  
  1513  		// Marshal and unmarshal it.
  1514  		// Assert the unmarshaled one is the same as the original.
  1515  		var unmarshaledProof ChangeProof
  1516  		protoProof := proof.ToProto()
  1517  		require.NoError(unmarshaledProof.UnmarshalProto(protoProof))
  1518  		require.Equal(proof, unmarshaledProof)
  1519  
  1520  		// Marshaling again should yield same result.
  1521  		protoUnmarshaledProof := unmarshaledProof.ToProto()
  1522  		require.Equal(protoProof, protoUnmarshaledProof)
  1523  	})
  1524  }
  1525  
  1526  func TestChangeProofUnmarshalProtoNil(t *testing.T) {
  1527  	var proof ChangeProof
  1528  	err := proof.UnmarshalProto(nil)
  1529  	require.ErrorIs(t, err, ErrNilChangeProof)
  1530  }
  1531  
  1532  func TestChangeProofUnmarshalProtoNilValue(t *testing.T) {
  1533  	now := time.Now().UnixNano()
  1534  	t.Logf("seed: %d", now)
  1535  	rand := rand.New(rand.NewSource(now)) // #nosec G404
  1536  
  1537  	// Make a random change proof.
  1538  	startProofLen := rand.Intn(32)
  1539  	startProof := make([]ProofNode, startProofLen)
  1540  	for i := 0; i < startProofLen; i++ {
  1541  		startProof[i] = newRandomProofNode(rand)
  1542  	}
  1543  
  1544  	endProofLen := rand.Intn(32)
  1545  	endProof := make([]ProofNode, endProofLen)
  1546  	for i := 0; i < endProofLen; i++ {
  1547  		endProof[i] = newRandomProofNode(rand)
  1548  	}
  1549  
  1550  	numKeyChanges := rand.Intn(128) + 1
  1551  	keyChanges := make([]KeyChange, numKeyChanges)
  1552  	for i := 0; i < numKeyChanges; i++ {
  1553  		keyLen := rand.Intn(32)
  1554  		key := make([]byte, keyLen)
  1555  		_, _ = rand.Read(key)
  1556  
  1557  		value := maybe.Nothing[[]byte]()
  1558  		hasValue := rand.Intn(2) == 0
  1559  		if hasValue {
  1560  			valueLen := rand.Intn(32)
  1561  			valueBytes := make([]byte, valueLen)
  1562  			_, _ = rand.Read(valueBytes)
  1563  			value = maybe.Some(valueBytes)
  1564  		}
  1565  
  1566  		keyChanges[i] = KeyChange{
  1567  			Key:   key,
  1568  			Value: value,
  1569  		}
  1570  	}
  1571  
  1572  	proof := ChangeProof{
  1573  		StartProof: startProof,
  1574  		EndProof:   endProof,
  1575  		KeyChanges: keyChanges,
  1576  	}
  1577  	protoProof := proof.ToProto()
  1578  	// Make a value nil
  1579  	protoProof.KeyChanges[0].Value = nil
  1580  
  1581  	var unmarshaledProof ChangeProof
  1582  	err := unmarshaledProof.UnmarshalProto(protoProof)
  1583  	require.ErrorIs(t, err, ErrNilMaybeBytes)
  1584  }
  1585  
  1586  func TestChangeProofUnmarshalProtoInvalidMaybe(t *testing.T) {
  1587  	protoProof := &pb.ChangeProof{
  1588  		KeyChanges: []*pb.KeyChange{
  1589  			{
  1590  				Key: []byte{1},
  1591  				Value: &pb.MaybeBytes{
  1592  					Value:     []byte{1},
  1593  					IsNothing: true,
  1594  				},
  1595  			},
  1596  		},
  1597  	}
  1598  
  1599  	var proof ChangeProof
  1600  	err := proof.UnmarshalProto(protoProof)
  1601  	require.ErrorIs(t, err, ErrInvalidMaybe)
  1602  }
  1603  
  1604  func FuzzProofProtoMarshalUnmarshal(f *testing.F) {
  1605  	f.Fuzz(func(
  1606  		t *testing.T,
  1607  		randSeed int64,
  1608  	) {
  1609  		require := require.New(t)
  1610  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1611  
  1612  		// Make a random proof.
  1613  		proofLen := rand.Intn(32)
  1614  		proofPath := make([]ProofNode, proofLen)
  1615  		for i := 0; i < proofLen; i++ {
  1616  			proofPath[i] = newRandomProofNode(rand)
  1617  		}
  1618  
  1619  		keyLen := rand.Intn(32)
  1620  		key := make([]byte, keyLen)
  1621  		_, _ = rand.Read(key)
  1622  
  1623  		hasValue := rand.Intn(2) == 1
  1624  		value := maybe.Nothing[[]byte]()
  1625  		if hasValue {
  1626  			valueLen := rand.Intn(32)
  1627  			valueBytes := make([]byte, valueLen)
  1628  			_, _ = rand.Read(valueBytes)
  1629  			value = maybe.Some(valueBytes)
  1630  		}
  1631  
  1632  		proof := Proof{
  1633  			Key:   ToKey(key),
  1634  			Value: value,
  1635  			Path:  proofPath,
  1636  		}
  1637  
  1638  		// Marshal and unmarshal it.
  1639  		// Assert the unmarshaled one is the same as the original.
  1640  		var unmarshaledProof Proof
  1641  		protoProof := proof.ToProto()
  1642  		require.NoError(unmarshaledProof.UnmarshalProto(protoProof))
  1643  		require.Equal(proof, unmarshaledProof)
  1644  
  1645  		// Marshaling again should yield same result.
  1646  		protoUnmarshaledProof := unmarshaledProof.ToProto()
  1647  		require.Equal(protoProof, protoUnmarshaledProof)
  1648  	})
  1649  }
  1650  
  1651  func TestProofProtoUnmarshal(t *testing.T) {
  1652  	type test struct {
  1653  		name        string
  1654  		proof       *pb.Proof
  1655  		expectedErr error
  1656  	}
  1657  
  1658  	tests := []test{
  1659  		{
  1660  			name:        "nil",
  1661  			proof:       nil,
  1662  			expectedErr: ErrNilProof,
  1663  		},
  1664  		{
  1665  			name:        "nil value",
  1666  			proof:       &pb.Proof{},
  1667  			expectedErr: ErrNilValue,
  1668  		},
  1669  		{
  1670  			name: "invalid maybe",
  1671  			proof: &pb.Proof{
  1672  				Value: &pb.MaybeBytes{
  1673  					Value:     []byte{1},
  1674  					IsNothing: true,
  1675  				},
  1676  			},
  1677  			expectedErr: ErrInvalidMaybe,
  1678  		},
  1679  	}
  1680  
  1681  	for _, tt := range tests {
  1682  		t.Run(tt.name, func(t *testing.T) {
  1683  			var proof Proof
  1684  			err := proof.UnmarshalProto(tt.proof)
  1685  			require.ErrorIs(t, err, tt.expectedErr)
  1686  		})
  1687  	}
  1688  }
  1689  
  1690  func FuzzRangeProofInvariants(f *testing.F) {
  1691  	deletePortion := 0.25
  1692  	f.Fuzz(func(
  1693  		t *testing.T,
  1694  		randSeed int64,
  1695  		startBytes []byte,
  1696  		endBytes []byte,
  1697  		maxProofLen uint,
  1698  		numKeyValues uint,
  1699  	) {
  1700  		require := require.New(t)
  1701  
  1702  		// Make sure proof length is valid
  1703  		if maxProofLen == 0 {
  1704  			t.SkipNow()
  1705  		}
  1706  		if numKeyValues == 0 {
  1707  			t.SkipNow()
  1708  		}
  1709  
  1710  		// Make sure proof bounds are valid
  1711  		if len(endBytes) != 0 && bytes.Compare(startBytes, endBytes) > 0 {
  1712  			t.SkipNow()
  1713  		}
  1714  
  1715  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1716  
  1717  		db, err := getBasicDB()
  1718  		require.NoError(err)
  1719  
  1720  		// Insert a bunch of random key values.
  1721  		insertRandomKeyValues(
  1722  			require,
  1723  			rand,
  1724  			[]database.Database{db},
  1725  			numKeyValues,
  1726  			deletePortion,
  1727  		)
  1728  
  1729  		start := maybe.Nothing[[]byte]()
  1730  		if len(startBytes) != 0 {
  1731  			start = maybe.Some(startBytes)
  1732  		}
  1733  
  1734  		end := maybe.Nothing[[]byte]()
  1735  		if len(endBytes) != 0 {
  1736  			end = maybe.Some(endBytes)
  1737  		}
  1738  
  1739  		rootID, err := db.GetMerkleRoot(context.Background())
  1740  		require.NoError(err)
  1741  
  1742  		rangeProof, err := db.GetRangeProof(
  1743  			context.Background(),
  1744  			start,
  1745  			end,
  1746  			int(maxProofLen),
  1747  		)
  1748  		if rootID == ids.Empty {
  1749  			require.ErrorIs(err, ErrEmptyProof)
  1750  			return
  1751  		}
  1752  		require.NoError(err)
  1753  
  1754  		require.NoError(rangeProof.Verify(
  1755  			context.Background(),
  1756  			start,
  1757  			end,
  1758  			rootID,
  1759  			db.tokenSize,
  1760  			db.hasher,
  1761  		))
  1762  
  1763  		// Make sure the start proof doesn't contain any nodes
  1764  		// that are in the end proof.
  1765  		endProofKeys := set.Set[Key]{}
  1766  		for _, node := range rangeProof.EndProof {
  1767  			endProofKeys.Add(node.Key)
  1768  		}
  1769  
  1770  		for _, node := range rangeProof.StartProof {
  1771  			require.NotContains(endProofKeys, node.Key)
  1772  		}
  1773  
  1774  		// Make sure the EndProof invariant is maintained
  1775  		switch {
  1776  		case end.IsNothing():
  1777  			if len(rangeProof.KeyValues) == 0 {
  1778  				if len(rangeProof.StartProof) == 0 {
  1779  					require.Len(rangeProof.EndProof, 1) // Just the root
  1780  					require.Empty(rangeProof.EndProof[0].Key.Bytes())
  1781  				} else {
  1782  					require.Empty(rangeProof.EndProof)
  1783  				}
  1784  			}
  1785  		case len(rangeProof.KeyValues) == 0:
  1786  			require.NotEmpty(rangeProof.EndProof)
  1787  
  1788  			// EndProof should be a proof for upper range bound.
  1789  			value := maybe.Nothing[[]byte]()
  1790  			upperRangeBoundVal, err := db.Get(endBytes)
  1791  			if err != nil {
  1792  				require.ErrorIs(err, database.ErrNotFound)
  1793  			} else {
  1794  				value = maybe.Some(upperRangeBoundVal)
  1795  			}
  1796  
  1797  			proof := Proof{
  1798  				Path:  rangeProof.EndProof,
  1799  				Key:   ToKey(endBytes),
  1800  				Value: value,
  1801  			}
  1802  
  1803  			rootID, err := db.GetMerkleRoot(context.Background())
  1804  			require.NoError(err)
  1805  
  1806  			require.NoError(proof.Verify(context.Background(), rootID, db.tokenSize, db.hasher))
  1807  		default:
  1808  			require.NotEmpty(rangeProof.EndProof)
  1809  
  1810  			greatestKV := rangeProof.KeyValues[len(rangeProof.KeyValues)-1]
  1811  			// EndProof should be a proof for largest key-value.
  1812  			proof := Proof{
  1813  				Path:  rangeProof.EndProof,
  1814  				Key:   ToKey(greatestKV.Key),
  1815  				Value: maybe.Some(greatestKV.Value),
  1816  			}
  1817  
  1818  			rootID, err := db.GetMerkleRoot(context.Background())
  1819  			require.NoError(err)
  1820  
  1821  			require.NoError(proof.Verify(context.Background(), rootID, db.tokenSize, db.hasher))
  1822  		}
  1823  	})
  1824  }
  1825  
  1826  func FuzzProofVerification(f *testing.F) {
  1827  	deletePortion := 0.25
  1828  	f.Fuzz(func(
  1829  		t *testing.T,
  1830  		key []byte,
  1831  		randSeed int64,
  1832  		numKeyValues uint,
  1833  	) {
  1834  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1835  		require := require.New(t)
  1836  		db, err := getBasicDB()
  1837  		require.NoError(err)
  1838  
  1839  		// Insert a bunch of random key values.
  1840  		insertRandomKeyValues(
  1841  			require,
  1842  			rand,
  1843  			[]database.Database{db},
  1844  			numKeyValues,
  1845  			deletePortion,
  1846  		)
  1847  
  1848  		if db.getMerkleRoot() == ids.Empty {
  1849  			return
  1850  		}
  1851  
  1852  		proof, err := db.GetProof(
  1853  			context.Background(),
  1854  			key,
  1855  		)
  1856  
  1857  		require.NoError(err)
  1858  
  1859  		rootID, err := db.GetMerkleRoot(context.Background())
  1860  		require.NoError(err)
  1861  
  1862  		require.NoError(proof.Verify(context.Background(), rootID, db.tokenSize, db.hasher))
  1863  
  1864  		// Insert a new key-value pair
  1865  		newKey := make([]byte, 32)
  1866  		_, _ = rand.Read(newKey) // #nosec G404
  1867  		newValue := make([]byte, 32)
  1868  		_, _ = rand.Read(newValue) // #nosec G404
  1869  		require.NoError(db.Put(newKey, newValue))
  1870  
  1871  		// Delete a key-value pair so database doesn't grow unbounded
  1872  		iter := db.NewIterator()
  1873  		deleteKey := iter.Key()
  1874  		iter.Release()
  1875  
  1876  		require.NoError(db.Delete(deleteKey))
  1877  	})
  1878  }
  1879  
  1880  // Generate change proofs and verify that they are valid.
  1881  func FuzzChangeProofVerification(f *testing.F) {
  1882  	const (
  1883  		numKeyValues  = defaultHistoryLength / 2
  1884  		deletePortion = 0.25
  1885  	)
  1886  
  1887  	f.Fuzz(func(
  1888  		t *testing.T,
  1889  		startBytes []byte,
  1890  		endBytes []byte,
  1891  		maxProofLen uint,
  1892  		randSeed int64,
  1893  	) {
  1894  		require := require.New(t)
  1895  		rand := rand.New(rand.NewSource(randSeed)) // #nosec G404
  1896  
  1897  		db, err := getBasicDB()
  1898  		require.NoError(err)
  1899  
  1900  		startRootID, err := db.GetMerkleRoot(context.Background())
  1901  		require.NoError(err)
  1902  
  1903  		// Insert a bunch of random key values.
  1904  		// Don't insert so many that we have insufficient history.
  1905  		insertRandomKeyValues(
  1906  			require,
  1907  			rand,
  1908  			[]database.Database{db},
  1909  			numKeyValues,
  1910  			deletePortion,
  1911  		)
  1912  
  1913  		endRootID, err := db.GetMerkleRoot(context.Background())
  1914  		require.NoError(err)
  1915  
  1916  		// Make sure proof bounds are valid
  1917  		if len(endBytes) != 0 && bytes.Compare(startBytes, endBytes) > 0 {
  1918  			return
  1919  		}
  1920  		// Make sure proof length is valid
  1921  		if maxProofLen == 0 {
  1922  			return
  1923  		}
  1924  
  1925  		start := maybe.Nothing[[]byte]()
  1926  		if len(startBytes) != 0 {
  1927  			start = maybe.Some(startBytes)
  1928  		}
  1929  
  1930  		end := maybe.Nothing[[]byte]()
  1931  		if len(endBytes) != 0 {
  1932  			end = maybe.Some(endBytes)
  1933  		}
  1934  
  1935  		changeProof, err := db.GetChangeProof(
  1936  			context.Background(),
  1937  			startRootID,
  1938  			endRootID,
  1939  			start,
  1940  			end,
  1941  			int(maxProofLen),
  1942  		)
  1943  		require.NoError(err)
  1944  
  1945  		require.NoError(db.VerifyChangeProof(
  1946  			context.Background(),
  1947  			changeProof,
  1948  			start,
  1949  			end,
  1950  			endRootID,
  1951  		))
  1952  	})
  1953  }