polygon/sync: fork choice logic (#9228)

This commit is contained in:
battlmonstr 2024-01-14 14:40:47 +01:00 committed by GitHub
parent d8b91c4d02
commit ac9f9e0a25
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,6 +1,7 @@
package sync package sync
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"time" "time"
@ -142,13 +143,29 @@ func (impl *canonicalChainBuilderImpl) Prune(newRootNum uint64) error {
return nil return nil
} }
// compareForkTreeNodes compares 2 fork tree nodes.
// It returns a positive number if the chain ending at node1 is "better" than the chain ending at node2.
// The better node belongs to the canonical chain, and it has:
// * a greater total difficulty,
// * or a smaller block number,
// * or a lexicographically greater hash.
// See: https://github.com/maticnetwork/bor/blob/master/core/forkchoice.go#L82
func compareForkTreeNodes(node1 *forkTreeNode, node2 *forkTreeNode) int {
difficultyDiff := int64(node1.totalDifficulty) - int64(node2.totalDifficulty)
if difficultyDiff != 0 {
return int(difficultyDiff)
}
blockNumDiff := node1.header.Number.Cmp(node2.header.Number)
if blockNumDiff != 0 {
return -blockNumDiff
}
return bytes.Compare(node1.headerHash.Bytes(), node2.headerHash.Bytes())
}
func (impl *canonicalChainBuilderImpl) updateTipIfNeeded(tipCandidate *forkTreeNode) { func (impl *canonicalChainBuilderImpl) updateTipIfNeeded(tipCandidate *forkTreeNode) {
if tipCandidate.totalDifficulty > impl.tip.totalDifficulty { if compareForkTreeNodes(tipCandidate, impl.tip) > 0 {
impl.tip = tipCandidate impl.tip = tipCandidate
} }
// else if tipCandidate.totalDifficulty == impl.tip.totalDifficulty {
// TODO: is it possible? which one is selected?
// }
} }
func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error { func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error {
@ -200,7 +217,7 @@ func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error {
// attach nodes for the new headers // attach nodes for the new headers
for i, header := range headers { for i, header := range headers {
if (header.Number == nil) && (header.Number.Uint64() != parent.header.Number.Uint64()+1) { if (header.Number == nil) || (header.Number.Uint64() != parent.header.Number.Uint64()+1) {
return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Number") return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Number")
} }