mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 23:26:44 +00:00
* fix: handle checkpoint ordering * create checkpoint verifier, add unit tests * fix: remove mutex * address comment for default checkpoint verifier Co-authored-by: Evgeny Danienko <6655321@bk.ru>
103 lines
3.2 KiB
Go
103 lines
3.2 KiB
Go
package eth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/consensus/bor"
|
|
"github.com/ethereum/go-ethereum/log"
|
|
)
|
|
|
|
var (
|
|
// errCheckpointCount is returned when we are unable to fetch
|
|
// the checkpoint count from local heimdall.
|
|
errCheckpointCount = errors.New("failed to fetch checkpoint count")
|
|
|
|
// errNoCheckpoint is returned when there is not checkpoint proposed
|
|
// by heimdall yet or heimdall is not in sync
|
|
errNoCheckpoint = errors.New("no checkpoint proposed")
|
|
|
|
// errCheckpoint is returned when we are unable to fetch the
|
|
// latest checkpoint from the local heimdall.
|
|
errCheckpoint = errors.New("failed to fetch latest checkpoint")
|
|
|
|
// errMissingCheckpoint is returned when we don't have the
|
|
// checkpoint blocks locally, yet.
|
|
errMissingCheckpoint = errors.New("missing checkpoint blocks")
|
|
|
|
// errRootHash is returned when we aren't able to calculate the root hash
|
|
// locally for a range of blocks.
|
|
errRootHash = errors.New("failed to get local root hash")
|
|
|
|
// errCheckpointRootHashMismatch is returned when the local root hash
|
|
// doesn't match with the root hash in checkpoint.
|
|
errCheckpointRootHashMismatch = errors.New("checkpoint roothash mismatch")
|
|
|
|
// errEndBlock is returned when we're unable to fetch a block locally.
|
|
errEndBlock = errors.New("failed to get end block")
|
|
)
|
|
|
|
// fetchWhitelistCheckpoints fetches the latest checkpoint/s from it's local heimdall
|
|
// and verifies the data against bor data.
|
|
func (h *ethHandler) fetchWhitelistCheckpoints(ctx context.Context, bor *bor.Bor, checkpointVerifier *checkpointVerifier, first bool) ([]uint64, []common.Hash, error) {
|
|
// Create an array for block number and block hashes
|
|
//nolint:prealloc
|
|
var (
|
|
blockNums []uint64 = make([]uint64, 0)
|
|
blockHashes []common.Hash = make([]common.Hash, 0)
|
|
)
|
|
|
|
// Fetch the checkpoint count from heimdall
|
|
count, err := bor.HeimdallClient.FetchCheckpointCount(ctx)
|
|
if err != nil {
|
|
log.Debug("Failed to fetch checkpoint count for whitelisting", "err", err)
|
|
return blockNums, blockHashes, errCheckpointCount
|
|
}
|
|
|
|
if count == 0 {
|
|
return blockNums, blockHashes, errNoCheckpoint
|
|
}
|
|
|
|
var (
|
|
start int64
|
|
end int64
|
|
)
|
|
|
|
// Prepare the checkpoint range to fetch
|
|
if count <= 10 {
|
|
start = 1
|
|
} else {
|
|
start = count - 10 + 1 // 10 is the max number of checkpoints to fetch
|
|
}
|
|
|
|
end = count
|
|
|
|
// If we're in not in the first iteration, only fetch the latest checkpoint
|
|
if !first {
|
|
start = count
|
|
}
|
|
|
|
for i := start; i <= end; i++ {
|
|
// fetch `i` indexed checkpoint from heimdall
|
|
checkpoint, err := bor.HeimdallClient.FetchCheckpoint(ctx, i)
|
|
if err != nil {
|
|
log.Debug("Failed to fetch latest checkpoint for whitelisting", "err", err)
|
|
return blockNums, blockHashes, errCheckpoint
|
|
}
|
|
|
|
// Verify if the checkpoint fetched can be added to the local whitelist entry or not
|
|
// If verified, it returns the hash of the end block of the checkpoint. If not,
|
|
// it will return appropriate error.
|
|
|
|
hash, err := checkpointVerifier.verify(ctx, h, checkpoint)
|
|
if err != nil {
|
|
return blockNums, blockHashes, err
|
|
}
|
|
|
|
blockNums = append(blockNums, checkpoint.EndBlock.Uint64())
|
|
blockHashes = append(blockHashes, common.HexToHash(hash))
|
|
}
|
|
|
|
return blockNums, blockHashes, nil
|
|
}
|