erigon-pulse/consensus/bor/finality/whitelist/service.go
Anshal Shukla 076dc33232
move borfinality package out of eth (#8407)
- Move borfinality out of eth package
- Adds nil pointer check in bor_verifier
2023-10-09 19:13:31 +01:00

192 lines
4.6 KiB
Go

package whitelist
import (
"errors"
"github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/consensus/bor/finality/rawdb"
"github.com/ledgerwatch/erigon/core/types"
)
var (
ErrMismatch = errors.New("mismatch error")
ErrNoRemote = errors.New("remote peer doesn't have a target block number")
)
type Service struct {
checkpointService
milestoneService
}
var ws *Service
func RegisterService(db kv.RwDB) {
ws = NewService(db)
}
func GetWhitelistingService() *Service {
return ws
}
func NewService(db kv.RwDB) *Service {
var checkpointDoExist = true
checkpointNumber, checkpointHash, err := rawdb.ReadFinality[*rawdb.Checkpoint](db)
if err != nil {
checkpointDoExist = false
}
var milestoneDoExist = true
milestoneNumber, milestoneHash, err := rawdb.ReadFinality[*rawdb.Milestone](db)
if err != nil {
milestoneDoExist = false
}
locked, lockedMilestoneNumber, lockedMilestoneHash, lockedMilestoneIDs, err := rawdb.ReadLockField(db)
if err != nil || !locked {
locked = false
lockedMilestoneIDs = make(map[string]struct{})
}
order, list, err := rawdb.ReadFutureMilestoneList(db)
if err != nil {
order = make([]uint64, 0)
list = make(map[uint64]common.Hash)
}
return &Service{
&checkpoint{
finality[*rawdb.Checkpoint]{
doExist: checkpointDoExist,
Number: checkpointNumber,
Hash: checkpointHash,
interval: 256,
db: db,
},
},
&milestone{
finality: finality[*rawdb.Milestone]{
doExist: milestoneDoExist,
Number: milestoneNumber,
Hash: milestoneHash,
interval: 256,
db: db,
},
Locked: locked,
LockedMilestoneNumber: lockedMilestoneNumber,
LockedMilestoneHash: lockedMilestoneHash,
LockedMilestoneIDs: lockedMilestoneIDs,
FutureMilestoneList: list,
FutureMilestoneOrder: order,
MaxCapacity: 10,
},
}
}
func (s *Service) PurgeWhitelistedCheckpoint() error {
s.checkpointService.Purge()
return nil
}
func (s *Service) PurgeWhitelistedMilestone() error {
s.milestoneService.Purge()
return nil
}
func (s *Service) GetWhitelistedCheckpoint() (bool, uint64, common.Hash) {
return s.checkpointService.Get()
}
func (s *Service) GetWhitelistedMilestone() (bool, uint64, common.Hash) {
return s.milestoneService.Get()
}
func (s *Service) ProcessMilestone(endBlockNum uint64, endBlockHash common.Hash) {
s.milestoneService.Process(endBlockNum, endBlockHash)
}
func (s *Service) ProcessCheckpoint(endBlockNum uint64, endBlockHash common.Hash) {
s.checkpointService.Process(endBlockNum, endBlockHash)
}
func (s *Service) IsValidChain(currentHeader uint64, chain []*types.Header) bool {
checkpointBool := s.checkpointService.IsValidChain(currentHeader, chain)
if !checkpointBool {
return checkpointBool
}
milestoneBool := s.milestoneService.IsValidChain(currentHeader, chain)
if !milestoneBool {
return milestoneBool
}
return true
}
func (s *Service) GetMilestoneIDsList() []string {
return s.milestoneService.GetMilestoneIDsList()
}
func splitChain(current uint64, chain []*types.Header) ([]*types.Header, []*types.Header) {
var (
pastChain []*types.Header
futureChain []*types.Header
first = chain[0].Number.Uint64()
last = chain[len(chain)-1].Number.Uint64()
)
if current >= first {
if len(chain) == 1 || current >= last {
pastChain = chain
} else {
pastChain = chain[:current-first+1]
}
}
if current < last {
if len(chain) == 1 || current < first {
futureChain = chain
} else {
futureChain = chain[current-first+1:]
}
}
return pastChain, futureChain
}
func isValidChain(currentHeader uint64, chain []*types.Header, doExist bool, number uint64, hash common.Hash, interval uint64) bool {
// Check if we have milestone to validate incoming chain in memory
if !doExist {
// We don't have any entry, no additional validation will be possible
return true
}
// Check if imported chain is less than whitelisted number
if chain[len(chain)-1].Number.Uint64() < number {
if currentHeader >= number { //If current tip of the chain is greater than whitelist number then return false
return false
} else {
return true
}
}
// Split the chain into past and future chain
pastChain, _ := splitChain(currentHeader, chain)
// Iterate over the chain and validate against the last milestone
// It will handle all cases when the incoming chain has atleast one milestone
for i := len(pastChain) - 1; i >= 0; i-- {
if pastChain[i].Number.Uint64() == number {
res := pastChain[i].Hash() == hash
return res
}
}
return true
}