diff --git a/beacon-chain/blockchain/BUILD.bazel b/beacon-chain/blockchain/BUILD.bazel index 21754c1a4..ed04a4fad 100644 --- a/beacon-chain/blockchain/BUILD.bazel +++ b/beacon-chain/blockchain/BUILD.bazel @@ -66,6 +66,7 @@ go_library( "//config/params:go_default_library", "//crypto/bls:go_default_library", "//encoding/bytesutil:go_default_library", + "//math:go_default_library", "//monitoring/tracing:go_default_library", "//proto/engine/v1:go_default_library", "//proto/eth/v1:go_default_library", diff --git a/beacon-chain/blockchain/process_block_helpers.go b/beacon-chain/blockchain/process_block_helpers.go index c8601989a..216bee820 100644 --- a/beacon-chain/blockchain/process_block_helpers.go +++ b/beacon-chain/blockchain/process_block_helpers.go @@ -11,6 +11,7 @@ import ( "github.com/prysmaticlabs/prysm/beacon-chain/state" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/encoding/bytesutil" + mathutil "github.com/prysmaticlabs/prysm/math" "github.com/prysmaticlabs/prysm/monitoring/tracing" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/block" @@ -402,10 +403,13 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e // We update the cache up to the last deposit index in the finalized block's state. // We can be confident that these deposits will be included in some block // because the Eth1 follow distance makes such long-range reorgs extremely unlikely. - eth1DepositIndex := int64(finalizedState.Eth1Data().DepositCount - 1) - s.cfg.DepositCache.InsertFinalizedDeposits(ctx, eth1DepositIndex) + eth1DepositIndex, err := mathutil.Int(finalizedState.Eth1DepositIndex()) + if err != nil { + return errors.Wrap(err, "could not cast eth1 deposit index") + } + s.cfg.DepositCache.InsertFinalizedDeposits(ctx, int64(eth1DepositIndex)) // Deposit proofs are only used during state transition and can be safely removed to save space. - if err = s.cfg.DepositCache.PruneProofs(ctx, eth1DepositIndex); err != nil { + if err = s.cfg.DepositCache.PruneProofs(ctx, int64(eth1DepositIndex)); err != nil { return errors.Wrap(err, "could not prune deposit proofs") } return nil diff --git a/beacon-chain/blockchain/process_block_test.go b/beacon-chain/blockchain/process_block_test.go index 8a2ae72ce..1203199ad 100644 --- a/beacon-chain/blockchain/process_block_test.go +++ b/beacon-chain/blockchain/process_block_test.go @@ -1516,6 +1516,7 @@ func TestInsertFinalizedDeposits(t *testing.T) { service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) gs = gs.Copy() assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10})) + assert.NoError(t, gs.SetEth1DepositIndex(7)) assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs)) zeroSig := [96]byte{} for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ { @@ -1529,8 +1530,64 @@ func TestInsertFinalizedDeposits(t *testing.T) { } assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'})) fDeposits := depositCache.FinalizedDeposits(ctx) - assert.Equal(t, 9, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly") - deps := depositCache.AllDeposits(ctx, big.NewInt(109)) + assert.Equal(t, 7, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly") + deps := depositCache.AllDeposits(ctx, big.NewInt(107)) + for _, d := range deps { + assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty") + } +} + +func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) { + ctx := context.Background() + opts := testServiceOptsWithDB(t) + depositCache, err := depositcache.New() + require.NoError(t, err) + opts = append(opts, WithDepositCache(depositCache)) + service, err := NewService(ctx, opts...) + require.NoError(t, err) + + gs, _ := util.DeterministicGenesisState(t, 32) + require.NoError(t, service.saveGenesisData(ctx, gs)) + gBlk, err := service.cfg.BeaconDB.GenesisBlock(ctx) + require.NoError(t, err) + gRoot, err := gBlk.Block().HashTreeRoot() + require.NoError(t, err) + service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]}) + gs = gs.Copy() + assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 7})) + assert.NoError(t, gs.SetEth1DepositIndex(5)) + assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs)) + gs2 := gs.Copy() + assert.NoError(t, gs2.SetEth1Data(ðpb.Eth1Data{DepositCount: 15})) + assert.NoError(t, gs2.SetEth1DepositIndex(12)) + assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}, gs2)) + zeroSig := [96]byte{} + for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ { + root := []byte(strconv.Itoa(int(i))) + assert.NoError(t, depositCache.InsertDeposit(ctx, ðpb.Deposit{Data: ðpb.Deposit_Data{ + PublicKey: bytesutil.FromBytes48([fieldparams.BLSPubkeyLength]byte{}), + WithdrawalCredentials: params.BeaconConfig().ZeroHash[:], + Amount: 0, + Signature: zeroSig[:], + }, Proof: [][]byte{root}}, 100+i, int64(i), bytesutil.ToBytes32(root))) + } + // Insert 3 deposits before hand. + depositCache.InsertFinalizedDeposits(ctx, 2) + + assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k'})) + fDeposits := depositCache.FinalizedDeposits(ctx) + assert.Equal(t, 5, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly") + + deps := depositCache.AllDeposits(ctx, big.NewInt(105)) + for _, d := range deps { + assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty") + } + + // Insert New Finalized State with higher deposit count. + assert.NoError(t, service.insertFinalizedDeposits(ctx, [32]byte{'m', 'o', 'c', 'k', '2'})) + fDeposits = depositCache.FinalizedDeposits(ctx) + assert.Equal(t, 12, int(fDeposits.MerkleTrieIndex), "Finalized deposits not inserted correctly") + deps = depositCache.AllDeposits(ctx, big.NewInt(112)) for _, d := range deps { assert.DeepEqual(t, [][]byte(nil), d.Proof, "Proofs are not empty") }