Fallback To Rebuilding Deposit Tries (#10562)

* fallback

* fix it

* make it clearer

* terence's review

Co-authored-by: terence tsao <terence@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
Nishant Das 2022-04-29 17:33:59 +08:00 committed by GitHub
parent 156e40e886
commit 2f29bb64f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 0 deletions

View File

@ -102,6 +102,7 @@ go_test(
"blocks_test.go",
"exit_test.go",
"proposer_attestations_test.go",
"proposer_deposits_test.go",
"proposer_execution_payload_test.go",
"proposer_sync_aggregate_test.go",
"proposer_test.go",

View File

@ -10,6 +10,7 @@ import (
"github.com/prysmaticlabs/prysm/config/params"
"github.com/prysmaticlabs/prysm/container/trie"
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc/codes"
@ -139,6 +140,13 @@ func (vs *Server) depositTrie(ctx context.Context, canonicalEth1Data *ethpb.Eth1
upToEth1DataDeposits := vs.DepositFetcher.NonFinalizedDeposits(ctx, finalizedDeposits.MerkleTrieIndex, canonicalEth1DataHeight)
insertIndex := finalizedDeposits.MerkleTrieIndex + 1
if shouldRebuildTrie(canonicalEth1Data.DepositCount, uint64(len(upToEth1DataDeposits))) {
log.WithFields(logrus.Fields{
"unfinalized deposits": len(upToEth1DataDeposits),
"total deposit count": canonicalEth1Data.DepositCount,
}).Warn("Too many unfinalized deposits, building a deposit trie from scratch.")
return vs.rebuildDepositTrie(ctx, canonicalEth1Data, canonicalEth1DataHeight)
}
for _, dep := range upToEth1DataDeposits {
depHash, err := dep.Data.HashTreeRoot()
if err != nil {
@ -210,3 +218,21 @@ func constructMerkleProof(trie *trie.SparseMerkleTrie, index int, deposit *ethpb
deposit.Proof = proof
return deposit, nil
}
// This checks whether we should fallback to rebuild the whole deposit trie.
func shouldRebuildTrie(totalDepCount, unFinalizedDeps uint64) bool {
if totalDepCount == 0 || unFinalizedDeps == 0 {
return false
}
// The total number interior nodes hashed in a binary trie would be
// x - 1, where x is the total number of leaves of the trie. For simplicity's
// sake we assume it as x here as this function is meant as a heuristic rather than
// and exact calculation.
//
// Since the effective_depth = log(x) , the total depth can be represented as
// depth = log(x) + k. We can then find the total number of nodes to be hashed by
// calculating y (log(x) + k) , where y is the number of unfinalized deposits. For
// the deposit trie, the value of log(x) + k is fixed at 32.
unFinalizedCompute := unFinalizedDeps * params.BeaconConfig().DepositContractTreeDepth
return unFinalizedCompute > totalDepCount
}

View File

@ -0,0 +1,56 @@
package validator
import "testing"
func TestShouldFallback(t *testing.T) {
tests := []struct {
name string
totalDepCount uint64
unFinalizedDeps uint64
want bool
}{
{
name: "0 dep count",
totalDepCount: 0,
unFinalizedDeps: 100,
want: false,
},
{
name: "0 unfinalized count",
totalDepCount: 100,
unFinalizedDeps: 0,
want: false,
},
{
name: "equal number of deposits and non finalized deposits",
totalDepCount: 1000,
unFinalizedDeps: 1000,
want: true,
},
{
name: "large number of non finalized deposits",
totalDepCount: 300000,
unFinalizedDeps: 100000,
want: true,
},
{
name: "small number of non finalized deposits",
totalDepCount: 300000,
unFinalizedDeps: 2000,
want: false,
},
{
name: "unfinalized deposits beyond threshold",
totalDepCount: 300000,
unFinalizedDeps: 10000,
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := shouldRebuildTrie(tt.totalDepCount, tt.unFinalizedDeps); got != tt.want {
t.Errorf("shouldRebuildTrie() = %v, want %v", got, tt.want)
}
})
}
}