mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 21:08:10 -05:00
fuzz: Add fuzz tests for sparse merkle trie (#10662)
* Add fuzz tests for sparse merkle trie and change HTR signature to return an error * fix capitalization of error message
This commit is contained in:
@@ -221,7 +221,8 @@ func TestChainService_InitializeBeaconChain(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
trie, _, err := util.DepositTrieFromDeposits(deposits)
|
||||
require.NoError(t, err)
|
||||
hashTreeRoot := trie.HashTreeRoot()
|
||||
hashTreeRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
genState, err := transition.EmptyGenesisState()
|
||||
require.NoError(t, err)
|
||||
err = genState.SetEth1Data(ðpb.Eth1Data{
|
||||
|
||||
@@ -430,7 +430,11 @@ func TestFinalizedDeposits_DepositsCachedCorrectly(t *testing.T) {
|
||||
}
|
||||
trie, err := trie.GenerateTrieFromItems(deps, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err, "Could not generate deposit trie")
|
||||
assert.Equal(t, trie.HashTreeRoot(), cachedDeposits.Deposits.HashTreeRoot())
|
||||
rootA, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
rootB, err := cachedDeposits.Deposits.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, rootA, rootB)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
@@ -488,7 +492,11 @@ func TestFinalizedDeposits_UtilizesPreviouslyCachedDeposits(t *testing.T) {
|
||||
}
|
||||
trie, err := trie.GenerateTrieFromItems(deps, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err, "Could not generate deposit trie")
|
||||
assert.Equal(t, trie.HashTreeRoot(), cachedDeposits.Deposits.HashTreeRoot())
|
||||
rootA, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
rootB, err := cachedDeposits.Deposits.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, rootA, rootB)
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_HandleZeroDeposits(t *testing.T) {
|
||||
|
||||
@@ -143,7 +143,8 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
beaconState, err := stateAltair.InitializeFromProto(ðpb.BeaconStateAltair{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
@@ -202,7 +203,8 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
||||
dep[0].Data.Signature = make([]byte, 96)
|
||||
trie, _, err := util.DepositTrieFromDeposits(dep)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
|
||||
@@ -173,7 +173,8 @@ func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
beaconState, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
@@ -233,7 +234,8 @@ func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
||||
dep[0].Data.Signature = make([]byte, 96)
|
||||
trie, _, err := util.DepositTrieFromDeposits(dep)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
@@ -289,7 +291,9 @@ func TestPreGenesisDeposits_SkipInvalidDeposit(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
dep[i].Proof = proof
|
||||
}
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: 1,
|
||||
@@ -376,7 +380,9 @@ func TestProcessDeposit_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T)
|
||||
},
|
||||
}
|
||||
balances := []uint64{0, 50}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
beaconState, err := v1.InitializeFromProto(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Balances: balances,
|
||||
|
||||
@@ -41,7 +41,10 @@ func UpdateGenesisEth1Data(state state.BeaconState, deposits []*ethpb.Deposit, e
|
||||
}
|
||||
}
|
||||
|
||||
depositRoot := t.HashTreeRoot()
|
||||
depositRoot, err := t.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eth1Data.DepositRoot = depositRoot[:]
|
||||
err = state.SetEth1Data(eth1Data)
|
||||
if err != nil {
|
||||
|
||||
@@ -138,7 +138,8 @@ func TestProcessDeposit_InvalidPublicKey(t *testing.T) {
|
||||
deposits[0].Proof, err = trie.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
@@ -178,7 +179,8 @@ func TestProcessDeposit_InvalidSignature(t *testing.T) {
|
||||
trie, err := trie.GenerateTrieFromItems([][]byte{leaf[:]}, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err)
|
||||
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
@@ -213,7 +215,8 @@ func TestProcessDeposit_UnableToVerify(t *testing.T) {
|
||||
|
||||
trie, _, err := util.DepositTrieFromDeposits(deposits)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: root[:],
|
||||
@@ -265,7 +268,8 @@ func TestProcessDeposit_IncompleteDeposit(t *testing.T) {
|
||||
|
||||
trie, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(t, err)
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositCount: 1,
|
||||
DepositRoot: root[:],
|
||||
@@ -281,7 +285,8 @@ func TestProcessDeposit_IncompleteDeposit(t *testing.T) {
|
||||
for i := 0; i < int(factor-1); i++ {
|
||||
assert.NoError(t, trie.Insert(dataRoot[:], i))
|
||||
|
||||
trieRoot := trie.HashTreeRoot()
|
||||
trieRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
eth1Data.DepositRoot = trieRoot[:]
|
||||
eth1Data.DepositCount = uint64(i + 1)
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
|
||||
depositHash, err := depositData.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to determine hashed value of deposit")
|
||||
return errors.Wrap(err, "unable to determine hashed value of deposit")
|
||||
}
|
||||
|
||||
// Defensive check to validate incoming index.
|
||||
@@ -158,20 +158,27 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
if !s.chainStartData.Chainstarted {
|
||||
proof, err := s.depositTrie.MerkleProof(int(index))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Unable to generate merkle proof for deposit")
|
||||
return errors.Wrap(err, "unable to generate merkle proof for deposit")
|
||||
}
|
||||
deposit.Proof = proof
|
||||
}
|
||||
|
||||
// We always store all historical deposits in the DB.
|
||||
err = s.cfg.depositCache.InsertDeposit(ctx, deposit, depositLog.BlockNumber, index, s.depositTrie.HashTreeRoot())
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to determine root of deposit trie")
|
||||
}
|
||||
err = s.cfg.depositCache.InsertDeposit(ctx, deposit, depositLog.BlockNumber, index, root)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to insert deposit into cache")
|
||||
}
|
||||
validData := true
|
||||
if !s.chainStartData.Chainstarted {
|
||||
s.chainStartData.ChainstartDeposits = append(s.chainStartData.ChainstartDeposits, deposit)
|
||||
root := s.depositTrie.HashTreeRoot()
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to determine root of deposit trie")
|
||||
}
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: uint64(len(s.chainStartData.ChainstartDeposits)),
|
||||
@@ -181,7 +188,11 @@ func (s *Service) ProcessDepositLog(ctx context.Context, depositLog gethTypes.Lo
|
||||
validData = false
|
||||
}
|
||||
} else {
|
||||
s.cfg.depositCache.InsertPendingDeposit(ctx, deposit, depositLog.BlockNumber, index, s.depositTrie.HashTreeRoot())
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to determine root of deposit trie")
|
||||
}
|
||||
s.cfg.depositCache.InsertPendingDeposit(ctx, deposit, depositLog.BlockNumber, index, root)
|
||||
}
|
||||
if validData {
|
||||
log.WithFields(logrus.Fields{
|
||||
@@ -225,12 +236,16 @@ func (s *Service) ProcessChainStart(genesisTime uint64, eth1BlockHash [32]byte,
|
||||
for i := range s.chainStartData.ChainstartDeposits {
|
||||
proof, err := s.depositTrie.MerkleProof(i)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to generate deposit proof %v", err)
|
||||
log.Errorf("unable to generate deposit proof %v", err)
|
||||
}
|
||||
s.chainStartData.ChainstartDeposits[i].Proof = proof
|
||||
}
|
||||
|
||||
root := s.depositTrie.HashTreeRoot()
|
||||
root, err := s.depositTrie.HashTreeRoot()
|
||||
if err != nil { // This should never happen.
|
||||
log.WithError(err).Error("unable to determine root of deposit trie, aborting chain start")
|
||||
return
|
||||
}
|
||||
s.chainStartData.Eth1Data = ðpb.Eth1Data{
|
||||
DepositCount: uint64(len(s.chainStartData.ChainstartDeposits)),
|
||||
DepositRoot: root[:],
|
||||
|
||||
@@ -197,10 +197,16 @@ func (vs *Server) rebuildDepositTrie(ctx context.Context, canonicalEth1Data *eth
|
||||
|
||||
// validate that the provided deposit trie matches up with the canonical eth1 data provided.
|
||||
func validateDepositTrie(trie *trie.SparseMerkleTrie, canonicalEth1Data *ethpb.Eth1Data) (bool, error) {
|
||||
if trie == nil || canonicalEth1Data == nil {
|
||||
return false, errors.New("nil trie or eth1data provided")
|
||||
}
|
||||
if trie.NumOfItems() != int(canonicalEth1Data.DepositCount) {
|
||||
return false, errors.Errorf("wanted the canonical count of %d but received %d", canonicalEth1Data.DepositCount, trie.NumOfItems())
|
||||
}
|
||||
rt := trie.HashTreeRoot()
|
||||
rt, err := trie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !bytes.Equal(rt[:], canonicalEth1Data.DepositRoot) {
|
||||
return false, errors.Errorf("wanted the canonical deposit root of %#x but received %#x", canonicalEth1Data.DepositRoot, rt)
|
||||
}
|
||||
|
||||
@@ -503,10 +503,14 @@ func TestProposer_PendingDeposits_OutsideEth1FollowWindow(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
|
||||
blk := util.NewBeaconBlock()
|
||||
@@ -638,10 +642,14 @@ func TestProposer_PendingDeposits_FollowsCorrectEth1Block(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -737,10 +745,14 @@ func TestProposer_PendingDeposits_CantReturnBelowStateEth1DepositIndex(t *testin
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -833,10 +845,14 @@ func TestProposer_PendingDeposits_CantReturnMoreThanMax(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, height.Uint64(), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -927,10 +943,14 @@ func TestProposer_PendingDeposits_CantReturnMoreThanDepositCount(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -1036,10 +1056,14 @@ func TestProposer_DepositTrie_UtilizesCachedFinalizedDeposits(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
@@ -1055,8 +1079,10 @@ func TestProposer_DepositTrie_UtilizesCachedFinalizedDeposits(t *testing.T) {
|
||||
trie, err := bs.depositTrie(ctx, ðpb.Eth1Data{}, big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)))
|
||||
require.NoError(t, err)
|
||||
|
||||
actualRoot := trie.HashTreeRoot()
|
||||
expectedRoot := depositTrie.HashTreeRoot()
|
||||
actualRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedRoot, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedRoot, actualRoot, "Incorrect deposit trie root")
|
||||
}
|
||||
|
||||
@@ -1146,10 +1172,14 @@ func TestProposer_DepositTrie_RebuildTrie(t *testing.T) {
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, dp.Eth1BlockHeight, dp.Index, root)
|
||||
}
|
||||
d := depositCache.AllDepositContainers(ctx)
|
||||
origDeposit, ok := proto.Clone(d[0].Deposit).(*ethpb.Deposit)
|
||||
@@ -1177,8 +1207,10 @@ func TestProposer_DepositTrie_RebuildTrie(t *testing.T) {
|
||||
trie, err := bs.depositTrie(ctx, ðpb.Eth1Data{}, big.NewInt(int64(params.BeaconConfig().Eth1FollowDistance)))
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedRoot := depositTrie.HashTreeRoot()
|
||||
actualRoot := trie.HashTreeRoot()
|
||||
expectedRoot, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
actualRoot, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, expectedRoot, actualRoot, "Incorrect deposit trie root")
|
||||
|
||||
}
|
||||
@@ -1230,7 +1262,8 @@ func TestProposer_ValidateDepositTrie(t *testing.T) {
|
||||
assert.NoError(t, trie.Insert([]byte{'a'}, 0))
|
||||
assert.NoError(t, trie.Insert([]byte{'b'}, 1))
|
||||
assert.NoError(t, trie.Insert([]byte{'c'}, 2))
|
||||
rt := trie.HashTreeRoot()
|
||||
rt, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
return ðpb.Eth1Data{DepositRoot: rt[:], DepositCount: 3, BlockHash: []byte{}}
|
||||
},
|
||||
trieCreator: func() *trie.SparseMerkleTrie {
|
||||
@@ -1274,7 +1307,9 @@ func TestProposer_Eth1Data_MajorityVote(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dc.Deposit, dc.Eth1BlockHeight, dc.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dc.Deposit, dc.Eth1BlockHeight, dc.Index, root))
|
||||
|
||||
t.Run("choose highest count", func(t *testing.T) {
|
||||
t.Skip()
|
||||
@@ -1976,10 +2011,14 @@ func TestProposer_Deposits_ReturnsEmptyList_IfLatestEth1DataEqGenesisEth1Block(t
|
||||
require.NoError(t, err, "Unable to determine hashed value of deposit")
|
||||
|
||||
assert.NoError(t, depositTrie.Insert(depositHash[:], int(dp.Index)))
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root))
|
||||
}
|
||||
for _, dp := range recentDeposits {
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, depositTrie.HashTreeRoot())
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
depositCache.InsertPendingDeposit(ctx, dp.Deposit, uint64(dp.Index), dp.Index, root)
|
||||
}
|
||||
|
||||
bs := &Server{
|
||||
|
||||
@@ -137,7 +137,9 @@ func TestWaitForActivation_ValidatorOriginallyExists(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 10 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 10 /*blockNum*/, 0, root))
|
||||
trie, err := v1.InitializeFromProtoUnsafe(beaconState)
|
||||
require.NoError(t, err)
|
||||
vs := &Server{
|
||||
|
||||
@@ -41,7 +41,9 @@ func TestValidatorStatus_DepositedEth1(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -84,7 +86,9 @@ func TestValidatorStatus_Deposited(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -134,7 +138,9 @@ func TestValidatorStatus_PartiallyDeposited(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -202,7 +208,9 @@ func TestValidatorStatus_Pending(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
@@ -247,7 +255,9 @@ func TestValidatorStatus_Active(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
|
||||
// Active because activation epoch <= current epoch < exit epoch.
|
||||
activeEpoch := helpers.ActivationExitEpoch(0)
|
||||
@@ -334,7 +344,9 @@ func TestValidatorStatus_Exiting(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -391,7 +403,9 @@ func TestValidatorStatus_Slashing(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -449,7 +463,9 @@ func TestValidatorStatus_Exited(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
@@ -532,11 +548,15 @@ func TestActivationStatus_OK(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, root))
|
||||
|
||||
dep = deposits[2]
|
||||
assert.NoError(t, depositTrie.Insert(dep.Data.Signature, 15))
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, depositTrie.HashTreeRoot()))
|
||||
root, err = depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, root))
|
||||
|
||||
vs := &Server{
|
||||
Ctx: context.Background(),
|
||||
@@ -677,7 +697,9 @@ func TestValidatorStatus_CorrectActivationQueue(t *testing.T) {
|
||||
deposit := ðpb.Deposit{
|
||||
Data: depData,
|
||||
}
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, int64(i), depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, int64(i), root))
|
||||
|
||||
}
|
||||
|
||||
@@ -758,10 +780,14 @@ func TestMultipleValidatorStatus_Pubkeys(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
dep := deposits[0]
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, dep, 10 /*blockNum*/, 0, root))
|
||||
dep = deposits[2]
|
||||
assert.NoError(t, depositTrie.Insert(dep.Data.Signature, 15))
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, depositTrie.HashTreeRoot()))
|
||||
root, err = depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(context.Background(), dep, 0, 1, root))
|
||||
|
||||
vs := &Server{
|
||||
Ctx: context.Background(),
|
||||
@@ -918,7 +944,9 @@ func TestValidatorStatus_Invalid(t *testing.T) {
|
||||
depositCache, err := depositcache.New()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, depositTrie.HashTreeRoot()))
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NoError(t, depositCache.InsertDeposit(ctx, deposit, 0 /*blockNum*/, 0, root))
|
||||
height := time.Unix(int64(params.BeaconConfig().Eth1FollowDistance), 0).Unix()
|
||||
p := &mockPOW.POWChain{
|
||||
TimesByHeight: map[int]uint64{
|
||||
|
||||
@@ -19,7 +19,11 @@ go_library(
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = ["sparse_merkle_test.go"],
|
||||
srcs = [
|
||||
"sparse_merkle_test.go",
|
||||
"sparse_merkle_trie_fuzz_test.go",
|
||||
],
|
||||
data = glob(["testdata/**"]),
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
@@ -31,5 +35,6 @@ go_test(
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//accounts/abi/bind:go_default_library",
|
||||
"@com_github_golang_protobuf//proto:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -81,7 +81,11 @@ func (m *SparseMerkleTrie) Items() [][]byte {
|
||||
// HashTreeRoot of the Merkle trie as defined in the deposit contract.
|
||||
// Spec Definition:
|
||||
// sha256(concat(node, self.to_little_endian_64(self.deposit_count), slice(zero_bytes32, start=0, len=24)))
|
||||
func (m *SparseMerkleTrie) HashTreeRoot() [32]byte {
|
||||
func (m *SparseMerkleTrie) HashTreeRoot() ([32]byte, error) {
|
||||
if len(m.branches) == 0 || len(m.branches[len(m.branches)-1]) == 0 {
|
||||
return [32]byte{}, errors.New("invalid branches provided to compute root")
|
||||
}
|
||||
|
||||
enc := [32]byte{}
|
||||
depositCount := uint64(len(m.originalItems))
|
||||
if len(m.originalItems) == 1 && bytes.Equal(m.originalItems[0], ZeroHashes[0][:]) {
|
||||
@@ -89,7 +93,7 @@ func (m *SparseMerkleTrie) HashTreeRoot() [32]byte {
|
||||
depositCount = 0
|
||||
}
|
||||
binary.LittleEndian.PutUint64(enc[:], depositCount)
|
||||
return hash.Hash(append(m.branches[len(m.branches)-1][0], enc[:]...))
|
||||
return hash.Hash(append(m.branches[len(m.branches)-1][0], enc[:]...)), nil
|
||||
}
|
||||
|
||||
// Insert an item into the trie.
|
||||
@@ -97,6 +101,12 @@ func (m *SparseMerkleTrie) Insert(item []byte, index int) error {
|
||||
if index < 0 {
|
||||
return fmt.Errorf("negative index provided: %d", index)
|
||||
}
|
||||
if len(m.branches) == 0 {
|
||||
return errors.New("invalid trie: no branches")
|
||||
}
|
||||
if m.depth > uint(len(m.branches)) {
|
||||
return errors.New("invalid trie: depth is greater than number of branches")
|
||||
}
|
||||
for index >= len(m.branches[0]) {
|
||||
m.branches[0] = append(m.branches[0], ZeroHashes[0][:])
|
||||
}
|
||||
@@ -143,11 +153,17 @@ func (m *SparseMerkleTrie) MerkleProof(index int) ([][]byte, error) {
|
||||
if index < 0 {
|
||||
return nil, fmt.Errorf("merkle index is negative: %d", index)
|
||||
}
|
||||
merkleIndex := uint(index)
|
||||
if len(m.branches) == 0 {
|
||||
return nil, errors.New("invalid trie: no branches")
|
||||
}
|
||||
leaves := m.branches[0]
|
||||
if index >= len(leaves) {
|
||||
return nil, fmt.Errorf("merkle index out of range in trie, max range: %d, received: %d", len(leaves), index)
|
||||
}
|
||||
if m.depth > uint(len(m.branches)) {
|
||||
return nil, errors.New("invalid trie: depth is greater than number of branches")
|
||||
}
|
||||
merkleIndex := uint(index)
|
||||
proof := make([][]byte, m.depth+1)
|
||||
for i := uint(0); i < m.depth; i++ {
|
||||
subIndex := (merkleIndex / (1 << i)) ^ 1
|
||||
@@ -185,6 +201,9 @@ func VerifyMerkleProofWithDepth(root, item []byte, merkleIndex uint64, proof [][
|
||||
if uint64(len(proof)) != depth+1 {
|
||||
return false
|
||||
}
|
||||
if depth >= 64 {
|
||||
return false // PowerOf2 would overflow.
|
||||
}
|
||||
node := bytesutil.ToBytes32(item)
|
||||
for i := uint64(0); i <= depth; i++ {
|
||||
if (merkleIndex / math.PowerOf2(i) % 2) != 0 {
|
||||
@@ -200,15 +219,10 @@ func VerifyMerkleProofWithDepth(root, item []byte, merkleIndex uint64, proof [][
|
||||
// VerifyMerkleProof given a trie root, a leaf, the generalized merkle index
|
||||
// of the leaf in the trie, and the proof itself.
|
||||
func VerifyMerkleProof(root, item []byte, merkleIndex uint64, proof [][]byte) bool {
|
||||
node := bytesutil.ToBytes32(item)
|
||||
for i := 0; i < len(proof); i++ {
|
||||
if (merkleIndex / math.PowerOf2(uint64(i)) % 2) != 0 {
|
||||
node = hash.Hash(append(proof[i], node[:]...))
|
||||
} else {
|
||||
node = hash.Hash(append(node[:], proof[i]...))
|
||||
if len(proof) == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return bytes.Equal(root, node[:])
|
||||
return VerifyMerkleProofWithDepth(root, item, merkleIndex, proof, uint64(len(proof)-1))
|
||||
}
|
||||
|
||||
// Copy performs a deep copy of the trie.
|
||||
|
||||
@@ -79,7 +79,9 @@ func TestMerkleTrieRoot_EmptyTrie(t *testing.T) {
|
||||
|
||||
depRoot, err := testAccount.Contract.GetDepositRoot(&bind.CallOpts{})
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, depRoot, trie.HashTreeRoot())
|
||||
root, err := trie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, depRoot, root)
|
||||
}
|
||||
|
||||
func TestGenerateTrieFromItems_NoItemsProvided(t *testing.T) {
|
||||
@@ -104,7 +106,8 @@ func TestMerkleTrie_VerifyMerkleProofWithDepth(t *testing.T) {
|
||||
proof, err := m.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int(params.BeaconConfig().DepositContractTreeDepth)+1, len(proof))
|
||||
root := m.HashTreeRoot()
|
||||
root, err := m.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], items[0], 0, proof, params.BeaconConfig().DepositContractTreeDepth); !ok {
|
||||
t.Error("First Merkle proof did not verify")
|
||||
}
|
||||
@@ -130,7 +133,8 @@ func TestMerkleTrie_VerifyMerkleProof(t *testing.T) {
|
||||
proof, err := m.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int(params.BeaconConfig().DepositContractTreeDepth)+1, len(proof))
|
||||
root := m.HashTreeRoot()
|
||||
root, err := m.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
if ok := trie.VerifyMerkleProof(root[:], items[0], 0, proof); !ok {
|
||||
t.Error("First Merkle proof did not verify")
|
||||
}
|
||||
@@ -170,14 +174,16 @@ func TestMerkleTrie_VerifyMerkleProof_TrieUpdated(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
proof, err := m.MerkleProof(0)
|
||||
require.NoError(t, err)
|
||||
root := m.HashTreeRoot()
|
||||
root, err := m.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, trie.VerifyMerkleProofWithDepth(root[:], items[0], 0, proof, depth))
|
||||
|
||||
// Now we update the trie.
|
||||
assert.NoError(t, m.Insert([]byte{5}, 3))
|
||||
proof, err = m.MerkleProof(3)
|
||||
require.NoError(t, err)
|
||||
root = m.HashTreeRoot()
|
||||
root, err = m.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], []byte{5}, 3, proof, depth); !ok {
|
||||
t.Error("Second Merkle proof did not verify")
|
||||
}
|
||||
@@ -200,10 +206,13 @@ func TestRoundtripProto_OK(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
protoTrie := m.ToProto()
|
||||
depositRoot := m.HashTreeRoot()
|
||||
depositRoot, err := m.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
newTrie := trie.CreateTrieFromProto(protoTrie)
|
||||
require.DeepEqual(t, depositRoot, newTrie.HashTreeRoot())
|
||||
root, err := newTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, depositRoot, root)
|
||||
|
||||
}
|
||||
|
||||
@@ -221,8 +230,11 @@ func TestCopy_OK(t *testing.T) {
|
||||
if copiedTrie == source {
|
||||
t.Errorf("Original trie returned.")
|
||||
}
|
||||
copyHash := copiedTrie.HashTreeRoot()
|
||||
require.DeepEqual(t, copyHash, copiedTrie.HashTreeRoot())
|
||||
a, err := copiedTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
b, err := source.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, a, b)
|
||||
}
|
||||
|
||||
func BenchmarkGenerateTrieFromItems(b *testing.B) {
|
||||
@@ -296,7 +308,8 @@ func BenchmarkVerifyMerkleProofWithDepth(b *testing.B) {
|
||||
proof, err := m.MerkleProof(2)
|
||||
require.NoError(b, err)
|
||||
|
||||
root := m.HashTreeRoot()
|
||||
root, err := m.HashTreeRoot()
|
||||
require.NoError(b, err)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if ok := trie.VerifyMerkleProofWithDepth(root[:], items[2], 2, proof, params.BeaconConfig().DepositContractTreeDepth); !ok {
|
||||
|
||||
148
container/trie/sparse_merkle_trie_fuzz_test.go
Normal file
148
container/trie/sparse_merkle_trie_fuzz_test.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package trie_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/container/trie"
|
||||
"github.com/prysmaticlabs/prysm/crypto/hash"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
)
|
||||
|
||||
func FuzzSparseMerkleTrie_HashTreeRoot(f *testing.F) {
|
||||
h := hash.Hash([]byte("hi"))
|
||||
pb := ðpb.SparseMerkleTrie{
|
||||
Layers: []*ethpb.TrieLayer{
|
||||
{
|
||||
Layer: [][]byte{h[:]},
|
||||
},
|
||||
{
|
||||
Layer: [][]byte{h[:]},
|
||||
},
|
||||
{
|
||||
Layer: [][]byte{},
|
||||
},
|
||||
},
|
||||
Depth: 4,
|
||||
}
|
||||
b, err := proto.Marshal(pb)
|
||||
require.NoError(f, err)
|
||||
f.Add(b)
|
||||
|
||||
f.Fuzz(func(t *testing.T, b []byte) {
|
||||
pb := ðpb.SparseMerkleTrie{}
|
||||
if err := proto.Unmarshal(b, pb); err != nil {
|
||||
return
|
||||
}
|
||||
_, err := trie.CreateTrieFromProto(pb).HashTreeRoot()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func FuzzSparseMerkleTrie_MerkleProof(f *testing.F) {
|
||||
h := hash.Hash([]byte("hi"))
|
||||
pb := ðpb.SparseMerkleTrie{
|
||||
Layers: []*ethpb.TrieLayer{
|
||||
{
|
||||
Layer: [][]byte{h[:]},
|
||||
},
|
||||
{
|
||||
Layer: [][]byte{h[:]},
|
||||
},
|
||||
{
|
||||
Layer: [][]byte{},
|
||||
},
|
||||
},
|
||||
Depth: 4,
|
||||
}
|
||||
b, err := proto.Marshal(pb)
|
||||
require.NoError(f, err)
|
||||
f.Add(b, 0)
|
||||
|
||||
f.Fuzz(func(t *testing.T, b []byte, i int) {
|
||||
pb := ðpb.SparseMerkleTrie{}
|
||||
if err := proto.Unmarshal(b, pb); err != nil {
|
||||
return
|
||||
}
|
||||
_, err := trie.CreateTrieFromProto(pb).MerkleProof(i)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func FuzzSparseMerkleTrie_Insert(f *testing.F) {
|
||||
h := hash.Hash([]byte("hi"))
|
||||
pb := ðpb.SparseMerkleTrie{
|
||||
Layers: []*ethpb.TrieLayer{
|
||||
{
|
||||
Layer: [][]byte{h[:]},
|
||||
},
|
||||
{
|
||||
Layer: [][]byte{h[:]},
|
||||
},
|
||||
{
|
||||
Layer: [][]byte{},
|
||||
},
|
||||
},
|
||||
Depth: 4,
|
||||
}
|
||||
b, err := proto.Marshal(pb)
|
||||
require.NoError(f, err)
|
||||
f.Add(b, []byte{}, 0)
|
||||
|
||||
f.Fuzz(func(t *testing.T, b, item []byte, i int) {
|
||||
pb := ðpb.SparseMerkleTrie{}
|
||||
if err := proto.Unmarshal(b, pb); err != nil {
|
||||
return
|
||||
}
|
||||
if err := trie.CreateTrieFromProto(pb).Insert(item, i); err != nil {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func FuzzSparseMerkleTrie_VerifyMerkleProofWithDepth(f *testing.F) {
|
||||
splitProofs := func(proofRaw []byte) [][]byte {
|
||||
var proofs [][]byte
|
||||
for i := 0; i < len(proofRaw); i += 32 {
|
||||
end := i + 32
|
||||
if end >= len(proofRaw) {
|
||||
end = len(proofRaw) - 1
|
||||
}
|
||||
proofs = append(proofs, proofRaw[i:end])
|
||||
}
|
||||
return proofs
|
||||
}
|
||||
|
||||
items := [][]byte{
|
||||
[]byte("A"),
|
||||
[]byte("B"),
|
||||
[]byte("C"),
|
||||
[]byte("D"),
|
||||
[]byte("E"),
|
||||
[]byte("F"),
|
||||
[]byte("G"),
|
||||
[]byte("H"),
|
||||
}
|
||||
m, err := trie.GenerateTrieFromItems(items, params.BeaconConfig().DepositContractTreeDepth)
|
||||
require.NoError(f, err)
|
||||
proof, err := m.MerkleProof(0)
|
||||
require.NoError(f, err)
|
||||
require.Equal(f, int(params.BeaconConfig().DepositContractTreeDepth)+1, len(proof))
|
||||
root, err := m.HashTreeRoot()
|
||||
require.NoError(f, err)
|
||||
var proofRaw []byte
|
||||
for _, p := range proof {
|
||||
proofRaw = append(proofRaw, p...)
|
||||
}
|
||||
f.Add(root[:], items[0], uint64(0), proofRaw, params.BeaconConfig().DepositContractTreeDepth)
|
||||
|
||||
f.Fuzz(func(t *testing.T, root, item []byte, merkleIndex uint64, proofRaw []byte, depth uint64) {
|
||||
trie.VerifyMerkleProofWithDepth(root, item, merkleIndex, splitProofs(proofRaw), depth)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
go test fuzz v1
|
||||
[]byte("")
|
||||
@@ -0,0 +1,4 @@
|
||||
go test fuzz v1
|
||||
[]byte("")
|
||||
[]byte("0")
|
||||
int(41)
|
||||
@@ -0,0 +1,3 @@
|
||||
go test fuzz v1
|
||||
[]byte("")
|
||||
int(63)
|
||||
@@ -0,0 +1,6 @@
|
||||
go test fuzz v1
|
||||
[]byte("0")
|
||||
[]byte("000000000")
|
||||
uint64(0)
|
||||
[]byte("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))00000000000000000000000000000000000000000000000000000000000000")
|
||||
uint64(71)
|
||||
@@ -23,7 +23,9 @@ func TestDepositTrieRoot_OK(t *testing.T) {
|
||||
depRoot, err := testAcc.Contract.GetDepositRoot(&bind.CallOpts{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, depRoot, localTrie.HashTreeRoot(), "Local deposit trie root and contract deposit trie root are not equal")
|
||||
localRoot, err := localTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, depRoot, localRoot, "Local deposit trie root and contract deposit trie root are not equal")
|
||||
|
||||
privKeys, pubKeys, err := interop.DeterministicallyGenerateKeys(0 /*startIndex*/, 101)
|
||||
require.NoError(t, err)
|
||||
@@ -47,7 +49,9 @@ func TestDepositTrieRoot_OK(t *testing.T) {
|
||||
assert.NoError(t, localTrie.Insert(item[:], i))
|
||||
depRoot, err = testAcc.Contract.GetDepositRoot(&bind.CallOpts{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, depRoot, localTrie.HashTreeRoot(), "Local deposit trie root and contract deposit trie root are not equal for index %d", i)
|
||||
localRoot, err := localTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, depRoot, localRoot, "Local deposit trie root and contract deposit trie root are not equal for index %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +65,9 @@ func TestDepositTrieRoot_Fail(t *testing.T) {
|
||||
depRoot, err := testAcc.Contract.GetDepositRoot(&bind.CallOpts{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, depRoot, localTrie.HashTreeRoot(), "Local deposit trie root and contract deposit trie root are not equal")
|
||||
localRoot, err := localTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, depRoot, localRoot, "Local deposit trie root and contract deposit trie root are not equal")
|
||||
|
||||
privKeys, pubKeys, err := interop.DeterministicallyGenerateKeys(0 /*startIndex*/, 101)
|
||||
require.NoError(t, err)
|
||||
@@ -89,6 +95,8 @@ func TestDepositTrieRoot_Fail(t *testing.T) {
|
||||
depRoot, err = testAcc.Contract.GetDepositRoot(&bind.CallOpts{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.NotEqual(t, depRoot, localTrie.HashTreeRoot(), "Local deposit trie root and contract deposit trie root are equal for index %d", i)
|
||||
localRoot, err := localTrie.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.NotEqual(t, depRoot, localRoot, "Local deposit trie root and contract deposit trie root are equal for index %d", i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,10 @@ func GenerateGenesisStateFromDepositData(
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not generate deposits from the deposit data provided")
|
||||
}
|
||||
root := trie.HashTreeRoot()
|
||||
root, err := trie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not hash tree root of deposit trie")
|
||||
}
|
||||
if genesisTime == 0 {
|
||||
genesisTime = uint64(time.Now().Unix())
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@ func TestGenerateGenesisState(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
deposits, err := interop.GenerateDepositsFromData(depositDataItems, tr)
|
||||
require.NoError(t, err)
|
||||
root := tr.HashTreeRoot()
|
||||
root, err := tr.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
genesisState, err := transition.GenesisBeaconState(context.Background(), deposits, 0, ð.Eth1Data{
|
||||
DepositRoot: root[:],
|
||||
DepositCount: uint64(len(deposits)),
|
||||
|
||||
@@ -242,7 +242,10 @@ func DeterministicEth1Data(size int) (*ethpb.Eth1Data, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create trie")
|
||||
}
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to compute deposit trie root")
|
||||
}
|
||||
eth1Data := ðpb.Eth1Data{
|
||||
BlockHash: root[:],
|
||||
DepositRoot: root[:],
|
||||
|
||||
@@ -276,7 +276,10 @@ func TestDepositTrieFromDeposits(t *testing.T) {
|
||||
depositTrie, _, err := DepositTrieFromDeposits(deposits)
|
||||
require.NoError(t, err)
|
||||
|
||||
root := depositTrie.HashTreeRoot()
|
||||
root, err := depositTrie.HashTreeRoot()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Equal(root[:], eth1Data.DepositRoot) {
|
||||
t.Fatal("expected deposit trie root to equal eth1data deposit root")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user