github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/cache/depositcache/pending_deposits.go (about) 1 package depositcache 2 3 import ( 4 "context" 5 "math/big" 6 "sort" 7 8 "github.com/prometheus/client_golang/prometheus" 9 "github.com/prometheus/client_golang/prometheus/promauto" 10 dbpb "github.com/prysmaticlabs/prysm/proto/beacon/db" 11 ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" 12 "github.com/prysmaticlabs/prysm/shared/hashutil" 13 "github.com/sirupsen/logrus" 14 "go.opencensus.io/trace" 15 ) 16 17 var ( 18 pendingDepositsCount = promauto.NewGauge(prometheus.GaugeOpts{ 19 Name: "beacondb_pending_deposits", 20 Help: "The number of pending deposits in the beaconDB in-memory database", 21 }) 22 ) 23 24 // PendingDepositsFetcher specifically outlines a struct that can retrieve deposits 25 // which have not yet been included in the chain. 26 type PendingDepositsFetcher interface { 27 PendingContainers(ctx context.Context, untilBlk *big.Int) []*dbpb.DepositContainer 28 } 29 30 // InsertPendingDeposit into the database. If deposit or block number are nil 31 // then this method does nothing. 32 func (dc *DepositCache) InsertPendingDeposit(ctx context.Context, d *ethpb.Deposit, blockNum uint64, index int64, depositRoot [32]byte) { 33 ctx, span := trace.StartSpan(ctx, "DepositsCache.InsertPendingDeposit") 34 defer span.End() 35 if d == nil { 36 log.WithFields(logrus.Fields{ 37 "block": blockNum, 38 "deposit": d, 39 }).Debug("Ignoring nil deposit insertion") 40 return 41 } 42 dc.depositsLock.Lock() 43 defer dc.depositsLock.Unlock() 44 dc.pendingDeposits = append(dc.pendingDeposits, 45 &dbpb.DepositContainer{Deposit: d, Eth1BlockHeight: blockNum, Index: index, DepositRoot: depositRoot[:]}) 46 pendingDepositsCount.Inc() 47 span.AddAttributes(trace.Int64Attribute("count", int64(len(dc.pendingDeposits)))) 48 } 49 50 // PendingDeposits returns a list of deposits until the given block number 51 // (inclusive). If no block is specified then this method returns all pending 52 // deposits. 53 func (dc *DepositCache) PendingDeposits(ctx context.Context, untilBlk *big.Int) []*ethpb.Deposit { 54 ctx, span := trace.StartSpan(ctx, "DepositsCache.PendingDeposits") 55 defer span.End() 56 57 depositCntrs := dc.PendingContainers(ctx, untilBlk) 58 59 var deposits []*ethpb.Deposit 60 for _, dep := range depositCntrs { 61 deposits = append(deposits, dep.Deposit) 62 } 63 64 return deposits 65 } 66 67 // PendingContainers returns a list of deposit containers until the given block number 68 // (inclusive). 69 func (dc *DepositCache) PendingContainers(ctx context.Context, untilBlk *big.Int) []*dbpb.DepositContainer { 70 ctx, span := trace.StartSpan(ctx, "DepositsCache.PendingDeposits") 71 defer span.End() 72 dc.depositsLock.RLock() 73 defer dc.depositsLock.RUnlock() 74 75 var depositCntrs []*dbpb.DepositContainer 76 for _, ctnr := range dc.pendingDeposits { 77 if untilBlk == nil || untilBlk.Uint64() >= ctnr.Eth1BlockHeight { 78 depositCntrs = append(depositCntrs, ctnr) 79 } 80 } 81 // Sort the deposits by Merkle index. 82 sort.SliceStable(depositCntrs, func(i, j int) bool { 83 return depositCntrs[i].Index < depositCntrs[j].Index 84 }) 85 86 span.AddAttributes(trace.Int64Attribute("count", int64(len(depositCntrs)))) 87 88 return depositCntrs 89 } 90 91 // RemovePendingDeposit from the database. The deposit is indexed by the 92 // Index. This method does nothing if deposit ptr is nil. 93 func (dc *DepositCache) RemovePendingDeposit(ctx context.Context, d *ethpb.Deposit) { 94 ctx, span := trace.StartSpan(ctx, "DepositsCache.RemovePendingDeposit") 95 defer span.End() 96 97 if d == nil { 98 log.Debug("Ignoring nil deposit removal") 99 return 100 } 101 102 depRoot, err := hashutil.HashProto(d) 103 if err != nil { 104 log.Errorf("Could not remove deposit %v", err) 105 return 106 } 107 108 dc.depositsLock.Lock() 109 defer dc.depositsLock.Unlock() 110 111 idx := -1 112 for i, ctnr := range dc.pendingDeposits { 113 hash, err := hashutil.HashProto(ctnr.Deposit) 114 if err != nil { 115 log.Errorf("Could not hash deposit %v", err) 116 continue 117 } 118 if hash == depRoot { 119 idx = i 120 break 121 } 122 } 123 124 if idx >= 0 { 125 dc.pendingDeposits = append(dc.pendingDeposits[:idx], dc.pendingDeposits[idx+1:]...) 126 pendingDepositsCount.Dec() 127 } 128 } 129 130 // PrunePendingDeposits removes any deposit which is older than the given deposit merkle tree index. 131 func (dc *DepositCache) PrunePendingDeposits(ctx context.Context, merkleTreeIndex int64) { 132 ctx, span := trace.StartSpan(ctx, "DepositsCache.PrunePendingDeposits") 133 defer span.End() 134 135 if merkleTreeIndex == 0 { 136 log.Debug("Ignoring 0 deposit removal") 137 return 138 } 139 140 dc.depositsLock.Lock() 141 defer dc.depositsLock.Unlock() 142 143 var cleanDeposits []*dbpb.DepositContainer 144 for _, dp := range dc.pendingDeposits { 145 if dp.Index >= merkleTreeIndex { 146 cleanDeposits = append(cleanDeposits, dp) 147 } 148 } 149 150 dc.pendingDeposits = cleanDeposits 151 pendingDepositsCount.Set(float64(len(dc.pendingDeposits))) 152 }