mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
Lint consensus/bor module
Cleanup, lint, and enable linters for consenssus/bor module. Disabled linter "gomnd" and "tagliatelle" because they are not easy to fix and the return on the time investment is very low. Disabled linter "prealloc" because it is not easy to guess and pre-allocate the slice accurately in many cases.
This commit is contained in:
parent
87a2e5224f
commit
12ab0f0240
14 changed files with 291 additions and 70 deletions
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
|
|
@ -6,7 +6,7 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- "**"
|
- "**"
|
||||||
types: [opened, synchronize]
|
types: [opened, synchronize, edited]
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: build-${{ github.event.pull_request.number || github.ref }}
|
group: build-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ linters:
|
||||||
- exportloopref
|
- exportloopref
|
||||||
- gocognit
|
- gocognit
|
||||||
- gofmt
|
- gofmt
|
||||||
- gomnd
|
# - gomnd
|
||||||
- gomoddirectives
|
- gomoddirectives
|
||||||
- gosec
|
- gosec
|
||||||
- makezero
|
- makezero
|
||||||
|
|
@ -38,11 +38,11 @@ linters:
|
||||||
- noctx
|
- noctx
|
||||||
#- nosprintfhostport # TODO: do we use IPv6?
|
#- nosprintfhostport # TODO: do we use IPv6?
|
||||||
- paralleltest
|
- paralleltest
|
||||||
- prealloc
|
# - prealloc
|
||||||
- predeclared
|
- predeclared
|
||||||
#- promlinter
|
#- promlinter
|
||||||
#- revive
|
#- revive
|
||||||
- tagliatelle
|
# - tagliatelle
|
||||||
- tenv
|
- tenv
|
||||||
- thelper
|
- thelper
|
||||||
- tparallel
|
- tparallel
|
||||||
|
|
@ -65,7 +65,7 @@ linters-settings:
|
||||||
local-prefixes: github.com/ethereum/go-ethereum
|
local-prefixes: github.com/ethereum/go-ethereum
|
||||||
|
|
||||||
nestif:
|
nestif:
|
||||||
min-complexity: 3
|
min-complexity: 5
|
||||||
|
|
||||||
prealloc:
|
prealloc:
|
||||||
for-loops: true
|
for-loops: true
|
||||||
|
|
@ -183,4 +183,4 @@ issues:
|
||||||
max-issues-per-linter: 0
|
max-issues-per-linter: 0
|
||||||
max-same-issues: 0
|
max-same-issues: 0
|
||||||
#new: true
|
#new: true
|
||||||
new-from-rev: origin/master
|
# new-from-rev: origin/master
|
||||||
4
Makefile
4
Makefile
|
|
@ -65,7 +65,9 @@ escape:
|
||||||
cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out
|
cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@./build/bin/golangci-lint run --config ./.golangci.yml
|
@./build/bin/golangci-lint run --config ./.golangci.yml \
|
||||||
|
internal/cli \
|
||||||
|
consensus/bor
|
||||||
|
|
||||||
lintci-deps:
|
lintci-deps:
|
||||||
rm -f ./build/bin/golangci-lint
|
rm -f ./build/bin/golangci-lint
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"github.com/xsleonard/go-merkle"
|
"github.com/xsleonard/go-merkle"
|
||||||
"golang.org/x/crypto/sha3"
|
"golang.org/x/crypto/sha3"
|
||||||
|
|
@ -44,6 +45,7 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,11 +61,11 @@ type difficultiesKV struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV {
|
func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV {
|
||||||
|
|
||||||
var ss []difficultiesKV
|
var ss []difficultiesKV
|
||||||
for k, v := range values {
|
for k, v := range values {
|
||||||
ss = append(ss, difficultiesKV{k, v})
|
ss = append(ss, difficultiesKV{k, v})
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(ss, func(i, j int) bool {
|
sort.Slice(ss, func(i, j int) bool {
|
||||||
return ss[i].Difficulty > ss[j].Difficulty
|
return ss[i].Difficulty > ss[j].Difficulty
|
||||||
})
|
})
|
||||||
|
|
@ -74,11 +76,15 @@ func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV {
|
||||||
// GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span
|
// GetSnapshotProposerSequence retrieves the in-turn signers of all sprints in a span
|
||||||
func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) {
|
func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigners, error) {
|
||||||
snapNumber := *number - 1
|
snapNumber := *number - 1
|
||||||
|
|
||||||
var difficulties = make(map[common.Address]uint64)
|
var difficulties = make(map[common.Address]uint64)
|
||||||
|
|
||||||
snap, err := api.GetSnapshot(&snapNumber)
|
snap, err := api.GetSnapshot(&snapNumber)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BlockSigners{}, err
|
return BlockSigners{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
proposer := snap.ValidatorSet.GetProposer().Address
|
proposer := snap.ValidatorSet.GetProposer().Address
|
||||||
proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)
|
proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer)
|
||||||
|
|
||||||
|
|
@ -88,6 +94,7 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne
|
||||||
if tempIndex < proposerIndex {
|
if tempIndex < proposerIndex {
|
||||||
tempIndex = tempIndex + len(signers)
|
tempIndex = tempIndex + len(signers)
|
||||||
}
|
}
|
||||||
|
|
||||||
difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex))
|
difficulties[signers[i]] = uint64(len(signers) - (tempIndex - proposerIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,6 +104,7 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return BlockSigners{}, err
|
return BlockSigners{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
diff := int(difficulties[*author])
|
diff := int(difficulties[*author])
|
||||||
blockSigners := &BlockSigners{
|
blockSigners := &BlockSigners{
|
||||||
Signers: rankedDifficulties,
|
Signers: rankedDifficulties,
|
||||||
|
|
@ -111,9 +119,11 @@ func (api *API) GetSnapshotProposerSequence(number *rpc.BlockNumber) (BlockSigne
|
||||||
func (api *API) GetSnapshotProposer(number *rpc.BlockNumber) (common.Address, error) {
|
func (api *API) GetSnapshotProposer(number *rpc.BlockNumber) (common.Address, error) {
|
||||||
*number -= 1
|
*number -= 1
|
||||||
snap, err := api.GetSnapshot(number)
|
snap, err := api.GetSnapshot(number)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap.ValidatorSet.GetProposer().Address, nil
|
return snap.ValidatorSet.GetProposer().Address, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +140,9 @@ func (api *API) GetAuthor(number *rpc.BlockNumber) (*common.Address, error) {
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
author, err := api.bor.Author(header)
|
author, err := api.bor.Author(header)
|
||||||
|
|
||||||
return &author, err
|
return &author, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,6 +152,7 @@ func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
return api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,10 +169,13 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap.signers(), nil
|
return snap.signers(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,10 +185,13 @@ func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) {
|
||||||
if header == nil {
|
if header == nil {
|
||||||
return nil, errUnknownBlock
|
return nil, errUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
snap, err := api.bor.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap.signers(), nil
|
return snap.signers(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,6 +201,7 @@ func (api *API) GetCurrentProposer() (common.Address, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap.ValidatorSet.GetProposer().Address, nil
|
return snap.ValidatorSet.GetProposer().Address, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -191,6 +211,7 @@ func (api *API) GetCurrentValidators() ([]*Validator, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return make([]*Validator, 0), err
|
return make([]*Validator, 0), err
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap.ValidatorSet.Validators, nil
|
return snap.ValidatorSet.Validators, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,26 +220,36 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
|
||||||
if err := api.initializeRootHashCache(); err != nil {
|
if err := api.initializeRootHashCache(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
key := getRootHashKey(start, end)
|
key := getRootHashKey(start, end)
|
||||||
|
|
||||||
if root, known := api.rootHashCache.Get(key); known {
|
if root, known := api.rootHashCache.Get(key); known {
|
||||||
return root.(string), nil
|
return root.(string), nil
|
||||||
}
|
}
|
||||||
length := uint64(end - start + 1)
|
|
||||||
|
length := end - start + 1
|
||||||
|
|
||||||
if length > MaxCheckpointLength {
|
if length > MaxCheckpointLength {
|
||||||
return "", &MaxCheckpointLengthExceededError{start, end}
|
return "", &MaxCheckpointLengthExceededError{start, end}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentHeaderNumber := api.chain.CurrentHeader().Number.Uint64()
|
currentHeaderNumber := api.chain.CurrentHeader().Number.Uint64()
|
||||||
|
|
||||||
if start > end || end > currentHeaderNumber {
|
if start > end || end > currentHeaderNumber {
|
||||||
return "", &InvalidStartEndBlockError{start, end, currentHeaderNumber}
|
return "", &InvalidStartEndBlockError{start, end, currentHeaderNumber}
|
||||||
}
|
}
|
||||||
|
|
||||||
blockHeaders := make([]*types.Header, end-start+1)
|
blockHeaders := make([]*types.Header, end-start+1)
|
||||||
wg := new(sync.WaitGroup)
|
wg := new(sync.WaitGroup)
|
||||||
concurrent := make(chan bool, 20)
|
concurrent := make(chan bool, 20)
|
||||||
|
|
||||||
for i := start; i <= end; i++ {
|
for i := start; i <= end; i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
concurrent <- true
|
concurrent <- true
|
||||||
|
|
||||||
go func(number uint64) {
|
go func(number uint64) {
|
||||||
blockHeaders[number-start] = api.chain.GetHeaderByNumber(uint64(number))
|
blockHeaders[number-start] = api.chain.GetHeaderByNumber(number)
|
||||||
|
|
||||||
<-concurrent
|
<-concurrent
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}(i)
|
}(i)
|
||||||
|
|
@ -227,6 +258,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
|
||||||
close(concurrent)
|
close(concurrent)
|
||||||
|
|
||||||
headers := make([][32]byte, nextPowerOfTwo(length))
|
headers := make([][32]byte, nextPowerOfTwo(length))
|
||||||
|
|
||||||
for i := 0; i < len(blockHeaders); i++ {
|
for i := 0; i < len(blockHeaders); i++ {
|
||||||
blockHeader := blockHeaders[i]
|
blockHeader := blockHeaders[i]
|
||||||
header := crypto.Keccak256(appendBytes32(
|
header := crypto.Keccak256(appendBytes32(
|
||||||
|
|
@ -237,6 +269,7 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
|
||||||
))
|
))
|
||||||
|
|
||||||
var arr [32]byte
|
var arr [32]byte
|
||||||
|
|
||||||
copy(arr[:], header)
|
copy(arr[:], header)
|
||||||
headers[i] = arr
|
headers[i] = arr
|
||||||
}
|
}
|
||||||
|
|
@ -245,8 +278,10 @@ func (api *API) GetRootHash(start uint64, end uint64) (string, error) {
|
||||||
if err := tree.Generate(convert(headers), sha3.NewLegacyKeccak256()); err != nil {
|
if err := tree.Generate(convert(headers), sha3.NewLegacyKeccak256()); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := hex.EncodeToString(tree.Root().Hash)
|
root := hex.EncodeToString(tree.Root().Hash)
|
||||||
api.rootHashCache.Add(key, root)
|
api.rootHashCache.Add(key, root)
|
||||||
|
|
||||||
return root, nil
|
return root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -255,6 +290,7 @@ func (api *API) initializeRootHashCache() error {
|
||||||
if api.rootHashCache == nil {
|
if api.rootHashCache == nil {
|
||||||
api.rootHashCache, err = lru.NewARC(10)
|
api.rootHashCache, err = lru.NewARC(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/ethdb"
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/event"
|
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
@ -56,9 +55,6 @@ var (
|
||||||
|
|
||||||
uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
|
uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
|
||||||
|
|
||||||
diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures
|
|
||||||
diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures
|
|
||||||
|
|
||||||
validatorHeaderBytesLength = common.AddressLength + 20 // address + power
|
validatorHeaderBytesLength = common.AddressLength + 20 // address + power
|
||||||
systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
|
systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE")
|
||||||
)
|
)
|
||||||
|
|
@ -72,18 +68,6 @@ var (
|
||||||
// that is not part of the local blockchain.
|
// that is not part of the local blockchain.
|
||||||
errUnknownBlock = errors.New("unknown block")
|
errUnknownBlock = errors.New("unknown block")
|
||||||
|
|
||||||
// errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition
|
|
||||||
// block has a beneficiary set to non-zeroes.
|
|
||||||
errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero")
|
|
||||||
|
|
||||||
// errInvalidVote is returned if a nonce value is something else that the two
|
|
||||||
// allowed constants of 0x00..0 or 0xff..f.
|
|
||||||
errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f")
|
|
||||||
|
|
||||||
// errInvalidCheckpointVote is returned if a checkpoint/epoch transition block
|
|
||||||
// has a vote nonce set to non-zeroes.
|
|
||||||
errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero")
|
|
||||||
|
|
||||||
// errMissingVanity is returned if a block's extra-data section is shorter than
|
// errMissingVanity is returned if a block's extra-data section is shorter than
|
||||||
// 32 bytes, which is required to store the signer vanity.
|
// 32 bytes, which is required to store the signer vanity.
|
||||||
errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
|
errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
|
||||||
|
|
@ -136,6 +120,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache, c *params.BorConfig
|
||||||
if len(header.Extra) < extraSeal {
|
if len(header.Extra) < extraSeal {
|
||||||
return common.Address{}, errMissingSignature
|
return common.Address{}, errMissingSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
signature := header.Extra[len(header.Extra)-extraSeal:]
|
signature := header.Extra[len(header.Extra)-extraSeal:]
|
||||||
|
|
||||||
// Recover the public key and the Ethereum address
|
// Recover the public key and the Ethereum address
|
||||||
|
|
@ -143,10 +128,13 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache, c *params.BorConfig
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return common.Address{}, err
|
return common.Address{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var signer common.Address
|
var signer common.Address
|
||||||
|
|
||||||
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
|
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
|
||||||
|
|
||||||
sigcache.Add(hash, signer)
|
sigcache.Add(hash, signer)
|
||||||
|
|
||||||
return signer, nil
|
return signer, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -155,6 +143,7 @@ func SealHash(header *types.Header, c *params.BorConfig) (hash common.Hash) {
|
||||||
hasher := sha3.NewLegacyKeccak256()
|
hasher := sha3.NewLegacyKeccak256()
|
||||||
encodeSigHeader(hasher, header, c)
|
encodeSigHeader(hasher, header, c)
|
||||||
hasher.Sum(hash[:0])
|
hasher.Sum(hash[:0])
|
||||||
|
|
||||||
return hash
|
return hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,11 +165,13 @@ func encodeSigHeader(w io.Writer, header *types.Header, c *params.BorConfig) {
|
||||||
header.MixDigest,
|
header.MixDigest,
|
||||||
header.Nonce,
|
header.Nonce,
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsJaipur(header.Number.Uint64()) {
|
if c.IsJaipur(header.Number.Uint64()) {
|
||||||
if header.BaseFee != nil {
|
if header.BaseFee != nil {
|
||||||
enc = append(enc, header.BaseFee)
|
enc = append(enc, header.BaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := rlp.Encode(w, enc); err != nil {
|
if err := rlp.Encode(w, enc); err != nil {
|
||||||
panic("can't encode: " + err.Error())
|
panic("can't encode: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -194,9 +185,11 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6
|
||||||
if number%c.Sprint == 0 {
|
if number%c.Sprint == 0 {
|
||||||
delay = c.ProducerDelay
|
delay = c.ProducerDelay
|
||||||
}
|
}
|
||||||
|
|
||||||
if succession > 0 {
|
if succession > 0 {
|
||||||
delay += uint64(succession) * c.CalculateBackupMultiplier(number)
|
delay += uint64(succession) * c.CalculateBackupMultiplier(number)
|
||||||
}
|
}
|
||||||
|
|
||||||
return delay
|
return delay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,6 +203,7 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6
|
||||||
func BorRLP(header *types.Header, c *params.BorConfig) []byte {
|
func BorRLP(header *types.Header, c *params.BorConfig) []byte {
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
encodeSigHeader(b, header, c)
|
encodeSigHeader(b, header, c)
|
||||||
|
|
||||||
return b.Bytes()
|
return b.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -233,7 +227,6 @@ type Bor struct {
|
||||||
HeimdallClient IHeimdallClient
|
HeimdallClient IHeimdallClient
|
||||||
WithoutHeimdall bool
|
WithoutHeimdall bool
|
||||||
|
|
||||||
scope event.SubscriptionScope
|
|
||||||
// The fields below are for testing only
|
// The fields below are for testing only
|
||||||
fakeDiff bool // Skip difficulty verifications
|
fakeDiff bool // Skip difficulty verifications
|
||||||
}
|
}
|
||||||
|
|
@ -314,6 +307,7 @@ func (c *Bor) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*types.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return abort, results
|
return abort, results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -325,6 +319,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
|
||||||
if header.Number == nil {
|
if header.Number == nil {
|
||||||
return errUnknownBlock
|
return errUnknownBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
|
|
||||||
// Don't waste time checking blocks from the future
|
// Don't waste time checking blocks from the future
|
||||||
|
|
@ -344,32 +339,40 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head
|
||||||
if !isSprintEnd && signersBytes != 0 {
|
if !isSprintEnd && signersBytes != 0 {
|
||||||
return errExtraValidators
|
return errExtraValidators
|
||||||
}
|
}
|
||||||
|
|
||||||
if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 {
|
if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 {
|
||||||
return errInvalidSpanValidators
|
return errInvalidSpanValidators
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the mix digest is zero as we don't have fork protection currently
|
// Ensure that the mix digest is zero as we don't have fork protection currently
|
||||||
if header.MixDigest != (common.Hash{}) {
|
if header.MixDigest != (common.Hash{}) {
|
||||||
return errInvalidMixDigest
|
return errInvalidMixDigest
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the block doesn't contain any uncles which are meaningless in PoA
|
// Ensure that the block doesn't contain any uncles which are meaningless in PoA
|
||||||
if header.UncleHash != uncleHash {
|
if header.UncleHash != uncleHash {
|
||||||
return errInvalidUncleHash
|
return errInvalidUncleHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
|
// Ensure that the block's difficulty is meaningful (may not be correct at this point)
|
||||||
if number > 0 {
|
if number > 0 {
|
||||||
if header.Difficulty == nil {
|
if header.Difficulty == nil {
|
||||||
return errInvalidDifficulty
|
return errInvalidDifficulty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the gas limit is <= 2^63-1
|
// Verify that the gas limit is <= 2^63-1
|
||||||
cap := uint64(0x7fffffffffffffff)
|
gasCap := uint64(0x7fffffffffffffff)
|
||||||
if header.GasLimit > cap {
|
|
||||||
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
|
if header.GasLimit > gasCap {
|
||||||
|
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, gasCap)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If all checks passed, validate any special fields for hard forks
|
// If all checks passed, validate any special fields for hard forks
|
||||||
if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
|
if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// All basic checks passed, verify cascading fields
|
// All basic checks passed, verify cascading fields
|
||||||
return c.verifyCascadingFields(chain, header, parents)
|
return c.verifyCascadingFields(chain, header, parents)
|
||||||
}
|
}
|
||||||
|
|
@ -380,9 +383,11 @@ func validateHeaderExtraField(extraBytes []byte) error {
|
||||||
if len(extraBytes) < extraVanity {
|
if len(extraBytes) < extraVanity {
|
||||||
return errMissingVanity
|
return errMissingVanity
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(extraBytes) < extraVanity+extraSeal {
|
if len(extraBytes) < extraVanity+extraSeal {
|
||||||
return errMissingSignature
|
return errMissingSignature
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,12 +398,14 @@ func validateHeaderExtraField(extraBytes []byte) error {
|
||||||
func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
|
func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
|
||||||
// The genesis block is the always valid dead-end
|
// The genesis block is the always valid dead-end
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
|
|
||||||
if number == 0 {
|
if number == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the block's timestamp isn't too close to it's parent
|
// Ensure that the block's timestamp isn't too close to it's parent
|
||||||
var parent *types.Header
|
var parent *types.Header
|
||||||
|
|
||||||
if len(parents) > 0 {
|
if len(parents) > 0 {
|
||||||
parent = parents[len(parents)-1]
|
parent = parents[len(parents)-1]
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -413,11 +420,13 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
|
||||||
if header.GasUsed > header.GasLimit {
|
if header.GasUsed > header.GasLimit {
|
||||||
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
|
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !chain.Config().IsLondon(header.Number) {
|
if !chain.Config().IsLondon(header.Number) {
|
||||||
// Verify BaseFee not present before EIP-1559 fork.
|
// Verify BaseFee not present before EIP-1559 fork.
|
||||||
if header.BaseFee != nil {
|
if header.BaseFee != nil {
|
||||||
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee)
|
return fmt.Errorf("invalid baseFee before fork: have %d, want <nil>", header.BaseFee)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
|
if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -432,6 +441,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
|
||||||
|
|
||||||
// Retrieve the snapshot needed to verify this header and cache it
|
// Retrieve the snapshot needed to verify this header and cache it
|
||||||
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
|
snap, err := c.snapshot(chain, number-1, header.ParentHash, parents)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -444,6 +454,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
|
||||||
currentValidators := snap.ValidatorSet.Copy().Validators
|
currentValidators := snap.ValidatorSet.Copy().Validators
|
||||||
// sort validator by address
|
// sort validator by address
|
||||||
sort.Sort(ValidatorsByAddress(currentValidators))
|
sort.Sort(ValidatorsByAddress(currentValidators))
|
||||||
|
|
||||||
for i, validator := range currentValidators {
|
for i, validator := range currentValidators {
|
||||||
copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes())
|
copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes())
|
||||||
}
|
}
|
||||||
|
|
@ -458,6 +469,7 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t
|
||||||
}
|
}
|
||||||
|
|
||||||
// snapshot retrieves the authorization snapshot at a given point in time.
|
// snapshot retrieves the authorization snapshot at a given point in time.
|
||||||
|
// nolint: gocognit
|
||||||
func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
|
func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
|
||||||
// Search for a snapshot in memory or on disk for checkpoints
|
// Search for a snapshot in memory or on disk for checkpoints
|
||||||
var (
|
var (
|
||||||
|
|
@ -465,10 +477,12 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
snap *Snapshot
|
snap *Snapshot
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//nolint:govet
|
||||||
for snap == nil {
|
for snap == nil {
|
||||||
// If an in-memory snapshot was found, use that
|
// If an in-memory snapshot was found, use that
|
||||||
if s, ok := c.recents.Get(hash); ok {
|
if s, ok := c.recents.Get(hash); ok {
|
||||||
snap = s.(*Snapshot)
|
snap = s.(*Snapshot)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -476,7 +490,9 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
if number%checkpointInterval == 0 {
|
if number%checkpointInterval == 0 {
|
||||||
if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil {
|
if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil {
|
||||||
log.Trace("Loaded snapshot from disk", "number", number, "hash", hash)
|
log.Trace("Loaded snapshot from disk", "number", number, "hash", hash)
|
||||||
|
|
||||||
snap = s
|
snap = s
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -486,6 +502,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
// up more headers than allowed to be reorged (chain reinit from a freezer),
|
// up more headers than allowed to be reorged (chain reinit from a freezer),
|
||||||
// consider the checkpoint trusted and snapshot it.
|
// consider the checkpoint trusted and snapshot it.
|
||||||
// TODO fix this
|
// TODO fix this
|
||||||
|
// nolint:nestif
|
||||||
if number == 0 {
|
if number == 0 {
|
||||||
checkpoint := chain.GetHeaderByNumber(number)
|
checkpoint := chain.GetHeaderByNumber(number)
|
||||||
if checkpoint != nil {
|
if checkpoint != nil {
|
||||||
|
|
@ -503,7 +520,9 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
if err := snap.store(c.db); err != nil {
|
if err := snap.store(c.db); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
|
log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -516,6 +535,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
if header.Hash() != hash || header.Number.Uint64() != number {
|
if header.Hash() != hash || header.Number.Uint64() != number {
|
||||||
return nil, consensus.ErrUnknownAncestor
|
return nil, consensus.ErrUnknownAncestor
|
||||||
}
|
}
|
||||||
|
|
||||||
parents = parents[:len(parents)-1]
|
parents = parents[:len(parents)-1]
|
||||||
} else {
|
} else {
|
||||||
// No explicit parents (or no more left), reach out to the database
|
// No explicit parents (or no more left), reach out to the database
|
||||||
|
|
@ -524,6 +544,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
return nil, consensus.ErrUnknownAncestor
|
return nil, consensus.ErrUnknownAncestor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
headers = append(headers, header)
|
headers = append(headers, header)
|
||||||
number, hash = number-1, header.ParentHash
|
number, hash = number-1, header.ParentHash
|
||||||
}
|
}
|
||||||
|
|
@ -542,6 +563,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.recents.Add(snap.Hash, snap)
|
c.recents.Add(snap.Hash, snap)
|
||||||
|
|
||||||
// If we've generated a new checkpoint snapshot, save to disk
|
// If we've generated a new checkpoint snapshot, save to disk
|
||||||
|
|
@ -549,8 +571,10 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
if err = snap.store(c.db); err != nil {
|
if err = snap.store(c.db); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash)
|
log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap, err
|
return snap, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -560,6 +584,7 @@ func (c *Bor) VerifyUncles(chain consensus.ChainReader, block *types.Block) erro
|
||||||
if len(block.Uncles()) > 0 {
|
if len(block.Uncles()) > 0 {
|
||||||
return errors.New("uncles not allowed")
|
return errors.New("uncles not allowed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -590,6 +615,7 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
||||||
// Check the UnauthorizedSignerError.Error() msg to see why we pass number-1
|
// Check the UnauthorizedSignerError.Error() msg to see why we pass number-1
|
||||||
return &UnauthorizedSignerError{number - 1, signer.Bytes()}
|
return &UnauthorizedSignerError{number - 1, signer.Bytes()}
|
||||||
|
|
@ -643,6 +669,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
||||||
if len(header.Extra) < extraVanity {
|
if len(header.Extra) < extraVanity {
|
||||||
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
|
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
header.Extra = header.Extra[:extraVanity]
|
header.Extra = header.Extra[:extraVanity]
|
||||||
|
|
||||||
// get validator set if number
|
// get validator set if number
|
||||||
|
|
@ -654,6 +681,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
||||||
|
|
||||||
// sort validator by address
|
// sort validator by address
|
||||||
sort.Sort(ValidatorsByAddress(newValidators))
|
sort.Sort(ValidatorsByAddress(newValidators))
|
||||||
|
|
||||||
for _, validator := range newValidators {
|
for _, validator := range newValidators {
|
||||||
header.Extra = append(header.Extra, validator.HeaderBytes()...)
|
header.Extra = append(header.Extra, validator.HeaderBytes()...)
|
||||||
}
|
}
|
||||||
|
|
@ -673,7 +701,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
||||||
|
|
||||||
var succession int
|
var succession int
|
||||||
// if signer is not empty
|
// if signer is not empty
|
||||||
if bytes.Compare(c.signer.Bytes(), common.Address{}.Bytes()) != 0 {
|
if !bytes.Equal(c.signer.Bytes(), common.Address{}.Bytes()) {
|
||||||
succession, err = snap.GetSignerSuccessionNumber(c.signer)
|
succession, err = snap.GetSignerSuccessionNumber(c.signer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -684,6 +712,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header) e
|
||||||
if header.Time < uint64(time.Now().Unix()) {
|
if header.Time < uint64(time.Now().Unix()) {
|
||||||
header.Time = uint64(time.Now().Unix())
|
header.Time = uint64(time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -693,7 +722,9 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
|
||||||
stateSyncData := []*types.StateSyncData{}
|
stateSyncData := []*types.StateSyncData{}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
|
|
||||||
if headerNumber%c.config.Sprint == 0 {
|
if headerNumber%c.config.Sprint == 0 {
|
||||||
cx := chainContext{Chain: chain, Bor: c}
|
cx := chainContext{Chain: chain, Bor: c}
|
||||||
// check and commit span
|
// check and commit span
|
||||||
|
|
@ -728,13 +759,17 @@ func (c *Bor) Finalize(chain consensus.ChainHeaderReader, header *types.Header,
|
||||||
|
|
||||||
func decodeGenesisAlloc(i interface{}) (core.GenesisAlloc, error) {
|
func decodeGenesisAlloc(i interface{}) (core.GenesisAlloc, error) {
|
||||||
var alloc core.GenesisAlloc
|
var alloc core.GenesisAlloc
|
||||||
|
|
||||||
b, err := json.Marshal(i)
|
b, err := json.Marshal(i)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &alloc); err != nil {
|
if err := json.Unmarshal(b, &alloc); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return alloc, nil
|
return alloc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -745,12 +780,14 @@ func (c *Bor) changeContractCodeIfNeeded(headerNumber uint64, state *state.State
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to decode genesis alloc: %v", err)
|
return fmt.Errorf("failed to decode genesis alloc: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for addr, account := range allocs {
|
for addr, account := range allocs {
|
||||||
log.Info("change contract code", "address", addr)
|
log.Info("change contract code", "address", addr)
|
||||||
state.SetCode(addr, account.Code)
|
state.SetCode(addr, account.Code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -856,10 +893,12 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
|
copy(header.Extra[len(header.Extra)-extraSeal:], sighash)
|
||||||
|
|
||||||
// Wait until sealing is terminated or delay timeout.
|
// Wait until sealing is terminated or delay timeout.
|
||||||
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
|
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-stop:
|
case <-stop:
|
||||||
|
|
@ -874,6 +913,7 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result
|
||||||
"in-turn-signer", snap.ValidatorSet.GetProposer().Address.Hex(),
|
"in-turn-signer", snap.ValidatorSet.GetProposer().Address.Hex(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info(
|
log.Info(
|
||||||
"Sealing successful",
|
"Sealing successful",
|
||||||
"number", number,
|
"number", number,
|
||||||
|
|
@ -887,6 +927,7 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result
|
||||||
log.Warn("Sealing result was not read by miner", "number", number, "sealhash", SealHash(header, c.config))
|
log.Warn("Sealing result was not read by miner", "number", number, "sealhash", SealHash(header, c.config))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -898,6 +939,7 @@ func (c *Bor) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, par
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return new(big.Int).SetUint64(snap.Difficulty(c.signer))
|
return new(big.Int).SetUint64(snap.Difficulty(c.signer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -948,6 +990,7 @@ func (c *Bor) GetCurrentSpan(headerHash common.Hash) (*Span, error) {
|
||||||
To: &toAddress,
|
To: &toAddress,
|
||||||
Data: &msgData,
|
Data: &msgData,
|
||||||
}, blockNr, nil)
|
}, blockNr, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -998,15 +1041,16 @@ func (c *Bor) GetCurrentValidators(headerHash common.Hash, blockNumber uint64) (
|
||||||
To: &toAddress,
|
To: &toAddress,
|
||||||
Data: &msgData,
|
Data: &msgData,
|
||||||
}, blockNr, nil)
|
}, blockNr, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
// return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ret0 = new([]common.Address)
|
ret0 = new([]common.Address)
|
||||||
ret1 = new([]*big.Int)
|
ret1 = new([]*big.Int)
|
||||||
)
|
)
|
||||||
|
|
||||||
out := &[]interface{}{
|
out := &[]interface{}{
|
||||||
ret0,
|
ret0,
|
||||||
ret1,
|
ret1,
|
||||||
|
|
@ -1034,13 +1078,16 @@ func (c *Bor) checkAndCommitSpan(
|
||||||
) error {
|
) error {
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
span, err := c.GetCurrentSpan(header.ParentHash)
|
span, err := c.GetCurrentSpan(header.ParentHash)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.needToCommitSpan(span, headerNumber) {
|
if c.needToCommitSpan(span, headerNumber) {
|
||||||
err := c.fetchAndCommitSpan(span.ID+1, state, header, chain)
|
err := c.fetchAndCommitSpan(span.ID+1, state, header, chain)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1072,10 +1119,11 @@ func (c *Bor) fetchAndCommitSpan(
|
||||||
var heimdallSpan HeimdallSpan
|
var heimdallSpan HeimdallSpan
|
||||||
|
|
||||||
if c.WithoutHeimdall {
|
if c.WithoutHeimdall {
|
||||||
s, err := c.getNextHeimdallSpanForTest(newSpanID, state, header, chain)
|
s, err := c.getNextHeimdallSpanForTest(newSpanID, header, chain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
heimdallSpan = *s
|
heimdallSpan = *s
|
||||||
} else {
|
} else {
|
||||||
response, err := c.HeimdallClient.FetchWithRetry(fmt.Sprintf("bor/span/%d", newSpanID), "")
|
response, err := c.HeimdallClient.FetchWithRetry(fmt.Sprintf("bor/span/%d", newSpanID), "")
|
||||||
|
|
@ -1102,7 +1150,9 @@ func (c *Bor) fetchAndCommitSpan(
|
||||||
for _, val := range heimdallSpan.ValidatorSet.Validators {
|
for _, val := range heimdallSpan.ValidatorSet.Validators {
|
||||||
validators = append(validators, val.MinimalVal())
|
validators = append(validators, val.MinimalVal())
|
||||||
}
|
}
|
||||||
|
|
||||||
validatorBytes, err := rlp.EncodeToBytes(validators)
|
validatorBytes, err := rlp.EncodeToBytes(validators)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -1112,13 +1162,16 @@ func (c *Bor) fetchAndCommitSpan(
|
||||||
for _, val := range heimdallSpan.SelectedProducers {
|
for _, val := range heimdallSpan.SelectedProducers {
|
||||||
producers = append(producers, val.MinimalVal())
|
producers = append(producers, val.MinimalVal())
|
||||||
}
|
}
|
||||||
|
|
||||||
producerBytes, err := rlp.EncodeToBytes(producers)
|
producerBytes, err := rlp.EncodeToBytes(producers)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// method
|
// method
|
||||||
method := "commitSpan"
|
method := "commitSpan"
|
||||||
|
|
||||||
log.Info("✅ Committing new span",
|
log.Info("✅ Committing new span",
|
||||||
"id", heimdallSpan.ID,
|
"id", heimdallSpan.ID,
|
||||||
"startBlock", heimdallSpan.StartBlock,
|
"startBlock", heimdallSpan.StartBlock,
|
||||||
|
|
@ -1156,6 +1209,7 @@ func (c *Bor) CommitStates(
|
||||||
stateSyncs := make([]*types.StateSyncData, 0)
|
stateSyncs := make([]*types.StateSyncData, 0)
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
_lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1)
|
_lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1166,7 +1220,13 @@ func (c *Bor) CommitStates(
|
||||||
"Fetching state updates from Heimdall",
|
"Fetching state updates from Heimdall",
|
||||||
"fromID", lastStateID+1,
|
"fromID", lastStateID+1,
|
||||||
"to", to.Format(time.RFC3339))
|
"to", to.Format(time.RFC3339))
|
||||||
|
|
||||||
eventRecords, err := c.HeimdallClient.FetchStateSyncEvents(lastStateID+1, to.Unix())
|
eventRecords, err := c.HeimdallClient.FetchStateSyncEvents(lastStateID+1, to.Unix())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Error occurred when fetching state sync events", err)
|
||||||
|
}
|
||||||
|
|
||||||
if c.config.OverrideStateSyncRecords != nil {
|
if c.config.OverrideStateSyncRecords != nil {
|
||||||
if val, ok := c.config.OverrideStateSyncRecords[strconv.FormatUint(number, 10)]; ok {
|
if val, ok := c.config.OverrideStateSyncRecords[strconv.FormatUint(number, 10)]; ok {
|
||||||
eventRecords = eventRecords[0:val]
|
eventRecords = eventRecords[0:val]
|
||||||
|
|
@ -1174,10 +1234,12 @@ func (c *Bor) CommitStates(
|
||||||
}
|
}
|
||||||
|
|
||||||
chainID := c.chainConfig.ChainID.String()
|
chainID := c.chainConfig.ChainID.String()
|
||||||
|
|
||||||
for _, eventRecord := range eventRecords {
|
for _, eventRecord := range eventRecords {
|
||||||
if eventRecord.ID <= lastStateID {
|
if eventRecord.ID <= lastStateID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil {
|
if err := validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil {
|
||||||
log.Error(err.Error())
|
log.Error(err.Error())
|
||||||
break
|
break
|
||||||
|
|
@ -1196,6 +1258,7 @@ func (c *Bor) CommitStates(
|
||||||
}
|
}
|
||||||
lastStateID++
|
lastStateID++
|
||||||
}
|
}
|
||||||
|
|
||||||
return stateSyncs, nil
|
return stateSyncs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1204,6 +1267,7 @@ func validateEventRecord(eventRecord *EventRecordWithTime, number uint64, to tim
|
||||||
if lastStateID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) {
|
if lastStateID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) {
|
||||||
return &InvalidStateReceivedError{number, lastStateID, &to, eventRecord}
|
return &InvalidStateReceivedError{number, lastStateID, &to, eventRecord}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1217,12 +1281,12 @@ func (c *Bor) SetHeimdallClient(h IHeimdallClient) {
|
||||||
|
|
||||||
func (c *Bor) getNextHeimdallSpanForTest(
|
func (c *Bor) getNextHeimdallSpanForTest(
|
||||||
newSpanID uint64,
|
newSpanID uint64,
|
||||||
state *state.StateDB,
|
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
chain core.ChainContext,
|
chain core.ChainContext,
|
||||||
) (*HeimdallSpan, error) {
|
) (*HeimdallSpan, error) {
|
||||||
headerNumber := header.Number.Uint64()
|
headerNumber := header.Number.Uint64()
|
||||||
span, err := c.GetCurrentSpan(header.ParentHash)
|
span, err := c.GetCurrentSpan(header.ParentHash)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1242,12 +1306,14 @@ func (c *Bor) getNextHeimdallSpanForTest(
|
||||||
} else {
|
} else {
|
||||||
span.StartBlock = span.EndBlock + 1
|
span.StartBlock = span.EndBlock + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
span.EndBlock = span.StartBlock + (100 * c.config.Sprint) - 1
|
span.EndBlock = span.StartBlock + (100 * c.config.Sprint) - 1
|
||||||
|
|
||||||
selectedProducers := make([]Validator, len(snap.ValidatorSet.Validators))
|
selectedProducers := make([]Validator, len(snap.ValidatorSet.Validators))
|
||||||
for i, v := range snap.ValidatorSet.Validators {
|
for i, v := range snap.ValidatorSet.Validators {
|
||||||
selectedProducers[i] = *v
|
selectedProducers[i] = *v
|
||||||
}
|
}
|
||||||
|
|
||||||
heimdallSpan := &HeimdallSpan{
|
heimdallSpan := &HeimdallSpan{
|
||||||
Span: *span,
|
Span: *span,
|
||||||
ValidatorSet: *snap.ValidatorSet,
|
ValidatorSet: *snap.ValidatorSet,
|
||||||
|
|
@ -1335,10 +1401,11 @@ func applyMessage(
|
||||||
|
|
||||||
func validatorContains(a []*Validator, x *Validator) (*Validator, bool) {
|
func validatorContains(a []*Validator, x *Validator) (*Validator, bool) {
|
||||||
for _, n := range a {
|
for _, n := range a {
|
||||||
if bytes.Compare(n.Address.Bytes(), x.Address.Bytes()) == 0 {
|
if bytes.Equal(n.Address.Bytes(), x.Address.Bytes()) {
|
||||||
return n, true
|
return n, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1347,6 +1414,7 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator)
|
||||||
oldVals := v.Validators
|
oldVals := v.Validators
|
||||||
|
|
||||||
var changes []*Validator
|
var changes []*Validator
|
||||||
|
|
||||||
for _, ov := range oldVals {
|
for _, ov := range oldVals {
|
||||||
if f, ok := validatorContains(newVals, ov); ok {
|
if f, ok := validatorContains(newVals, ov); ok {
|
||||||
ov.VotingPower = f.VotingPower
|
ov.VotingPower = f.VotingPower
|
||||||
|
|
@ -1363,7 +1431,10 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v.UpdateWithChangeSet(changes)
|
if err := v.UpdateWithChangeSet(changes); err != nil {
|
||||||
|
log.Error("Error while updating change set", err)
|
||||||
|
}
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
|
|
@ -12,10 +14,11 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGenesisContractChange(t *testing.T) {
|
func TestGenesisContractChange(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
addr0 := common.Address{0x1}
|
addr0 := common.Address{0x1}
|
||||||
|
|
||||||
b := &Bor{
|
b := &Bor{
|
||||||
|
|
@ -101,6 +104,8 @@ func TestGenesisContractChange(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncodeSigHeaderJaipur(t *testing.T) {
|
func TestEncodeSigHeaderJaipur(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
// As part of the EIP-1559 fork in mumbai, an incorrect seal hash
|
// As part of the EIP-1559 fork in mumbai, an incorrect seal hash
|
||||||
// was used for Bor that did not included the BaseFee. The Jaipur
|
// was used for Bor that did not included the BaseFee. The Jaipur
|
||||||
// block is a hard fork to fix that.
|
// block is a hard fork to fix that.
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ type EventRecordWithTime struct {
|
||||||
Time time.Time `json:"record_time" yaml:"record_time"`
|
Time time.Time `json:"record_time" yaml:"record_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string representatin of span
|
// String returns the string representations of span
|
||||||
func (e *EventRecordWithTime) String() string {
|
func (e *EventRecordWithTime) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"id %v, contract %v, data: %v, txHash: %v, logIndex: %v, chainId: %v, time %s",
|
"id %v, contract %v, data: %v, txHash: %v, logIndex: %v, chainId: %v, time %s",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ func NewGenesisContractsClient(
|
||||||
) *GenesisContractsClient {
|
) *GenesisContractsClient {
|
||||||
vABI, _ := abi.JSON(strings.NewReader(validatorsetABI))
|
vABI, _ := abi.JSON(strings.NewReader(validatorsetABI))
|
||||||
sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI))
|
sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI))
|
||||||
|
|
||||||
return &GenesisContractsClient{
|
return &GenesisContractsClient{
|
||||||
validatorSetABI: vABI,
|
validatorSetABI: vABI,
|
||||||
stateReceiverABI: sABI,
|
stateReceiverABI: sABI,
|
||||||
|
|
@ -56,21 +57,27 @@ func (gc *GenesisContractsClient) CommitState(
|
||||||
) error {
|
) error {
|
||||||
eventRecord := event.BuildEventRecord()
|
eventRecord := event.BuildEventRecord()
|
||||||
recordBytes, err := rlp.EncodeToBytes(eventRecord)
|
recordBytes, err := rlp.EncodeToBytes(eventRecord)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
method := "commitState"
|
method := "commitState"
|
||||||
t := event.Time.Unix()
|
t := event.Time.Unix()
|
||||||
data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes)
|
data, err := gc.stateReceiverABI.Pack(method, big.NewInt(0).SetInt64(t), recordBytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to pack tx for commitState", "error", err)
|
log.Error("Unable to pack tx for commitState", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("→ committing new state", "eventRecord", event.String())
|
log.Info("→ committing new state", "eventRecord", event.String())
|
||||||
|
|
||||||
msg := getSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
|
msg := getSystemMessage(common.HexToAddress(gc.StateReceiverContract), data)
|
||||||
if err := applyMessage(msg, state, header, gc.chainConfig, chCtx); err != nil {
|
if err := applyMessage(msg, state, header, gc.chainConfig, chCtx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -78,6 +85,7 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int,
|
||||||
blockNr := rpc.BlockNumber(snapshotNumber)
|
blockNr := rpc.BlockNumber(snapshotNumber)
|
||||||
method := "lastStateId"
|
method := "lastStateId"
|
||||||
data, err := gc.stateReceiverABI.Pack(method)
|
data, err := gc.stateReceiverABI.Pack(method)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to pack tx for LastStateId", "error", err)
|
log.Error("Unable to pack tx for LastStateId", "error", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -91,6 +99,7 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int,
|
||||||
To: &toAddress,
|
To: &toAddress,
|
||||||
Data: &msgData,
|
Data: &msgData,
|
||||||
}, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil)
|
}, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -99,5 +108,6 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int,
|
||||||
if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil {
|
if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return *ret, nil
|
return *ret, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@ package bor
|
||||||
|
|
||||||
func appendBytes32(data ...[]byte) []byte {
|
func appendBytes32(data ...[]byte) []byte {
|
||||||
var result []byte
|
var result []byte
|
||||||
|
|
||||||
for _, v := range data {
|
for _, v := range data {
|
||||||
paddedV, err := convertTo32(v)
|
paddedV := convertTo32(v)
|
||||||
if err == nil {
|
result = append(result, paddedV[:]...)
|
||||||
result = append(result, paddedV[:]...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,25 +24,29 @@ func nextPowerOfTwo(n uint64) uint64 {
|
||||||
n |= n >> 16
|
n |= n >> 16
|
||||||
n |= n >> 32
|
n |= n >> 32
|
||||||
n++
|
n++
|
||||||
|
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertTo32(input []byte) (output [32]byte, err error) {
|
func convertTo32(input []byte) (output [32]byte) {
|
||||||
l := len(input)
|
l := len(input)
|
||||||
if l > 32 || l == 0 {
|
if l > 32 || l == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
copy(output[32-l:], input[:])
|
copy(output[32-l:], input[:])
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func convert(input []([32]byte)) [][]byte {
|
func convert(input []([32]byte)) [][]byte {
|
||||||
var output [][]byte
|
var output [][]byte
|
||||||
|
|
||||||
for _, in := range input {
|
for _, in := range input {
|
||||||
newInput := make([]byte, len(in[:]))
|
newInput := make([]byte, len(in[:]))
|
||||||
copy(newInput, in[:])
|
copy(newInput, in[:])
|
||||||
output = append(output, newInput)
|
output = append(output, newInput)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,39 +40,49 @@ func NewHeimdallClient(urlString string) (*HeimdallClient, error) {
|
||||||
h := &HeimdallClient{
|
h := &HeimdallClient{
|
||||||
urlString: urlString,
|
urlString: urlString,
|
||||||
client: http.Client{
|
client: http.Client{
|
||||||
Timeout: time.Duration(5 * time.Second),
|
Timeout: 5 * time.Second,
|
||||||
},
|
},
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
return h, nil
|
return h, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) {
|
func (h *HeimdallClient) FetchStateSyncEvents(fromID uint64, to int64) ([]*EventRecordWithTime, error) {
|
||||||
eventRecords := make([]*EventRecordWithTime, 0)
|
eventRecords := make([]*EventRecordWithTime, 0)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
queryParams := fmt.Sprintf("from-id=%d&to-time=%d&limit=%d", fromID, to, stateFetchLimit)
|
queryParams := fmt.Sprintf("from-id=%d&to-time=%d&limit=%d", fromID, to, stateFetchLimit)
|
||||||
log.Info("Fetching state sync events", "queryParams", queryParams)
|
log.Info("Fetching state sync events", "queryParams", queryParams)
|
||||||
response, err := h.FetchWithRetry("clerk/event-record/list", queryParams)
|
response, err := h.FetchWithRetry("clerk/event-record/list", queryParams)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var _eventRecords []*EventRecordWithTime
|
var _eventRecords []*EventRecordWithTime
|
||||||
|
|
||||||
if response.Result == nil { // status 204
|
if response.Result == nil { // status 204
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(response.Result, &_eventRecords); err != nil {
|
if err := json.Unmarshal(response.Result, &_eventRecords); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
eventRecords = append(eventRecords, _eventRecords...)
|
eventRecords = append(eventRecords, _eventRecords...)
|
||||||
|
|
||||||
if len(_eventRecords) < stateFetchLimit {
|
if len(_eventRecords) < stateFetchLimit {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
fromID += uint64(stateFetchLimit)
|
fromID += uint64(stateFetchLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.SliceStable(eventRecords, func(i, j int) bool {
|
sort.SliceStable(eventRecords, func(i, j int) bool {
|
||||||
return eventRecords[i].ID < eventRecords[j].ID
|
return eventRecords[i].ID < eventRecords[j].ID
|
||||||
})
|
})
|
||||||
|
|
||||||
return eventRecords, nil
|
return eventRecords, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,7 +140,7 @@ func (h *HeimdallClient) FetchWithRetry(rawPath string, rawQuery string) (*Respo
|
||||||
|
|
||||||
// internal fetch method
|
// internal fetch method
|
||||||
func (h *HeimdallClient) internalFetch(u *url.URL) (*ResponseWithHeight, error) {
|
func (h *HeimdallClient) internalFetch(u *url.URL) (*ResponseWithHeight, error) {
|
||||||
res, err := h.client.Get(u.String())
|
res, err := h.client.Get(u.String()) // nolint: noctx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,6 @@ type Snapshot struct {
|
||||||
Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections
|
Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections
|
||||||
}
|
}
|
||||||
|
|
||||||
// signersAscending implements the sort interface to allow sorting a list of addresses
|
|
||||||
type signersAscending []common.Address
|
|
||||||
|
|
||||||
func (s signersAscending) Len() int { return len(s) }
|
|
||||||
func (s signersAscending) Less(i, j int) bool { return bytes.Compare(s[i][:], s[j][:]) < 0 }
|
|
||||||
func (s signersAscending) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|
||||||
|
|
||||||
// newSnapshot creates a new snapshot with the specified startup parameters. This
|
// newSnapshot creates a new snapshot with the specified startup parameters. This
|
||||||
// method does not initialize the set of recent signers, so only ever use if for
|
// method does not initialize the set of recent signers, so only ever use if for
|
||||||
// the genesis block.
|
// the genesis block.
|
||||||
|
|
@ -52,6 +45,7 @@ func newSnapshot(
|
||||||
ValidatorSet: NewValidatorSet(validators),
|
ValidatorSet: NewValidatorSet(validators),
|
||||||
Recents: make(map[uint64]common.Address),
|
Recents: make(map[uint64]common.Address),
|
||||||
}
|
}
|
||||||
|
|
||||||
return snap
|
return snap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,10 +55,13 @@ func loadSnapshot(config *params.BorConfig, sigcache *lru.ARCCache, db ethdb.Dat
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
snap := new(Snapshot)
|
snap := new(Snapshot)
|
||||||
|
|
||||||
if err := json.Unmarshal(blob, snap); err != nil {
|
if err := json.Unmarshal(blob, snap); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
snap.config = config
|
snap.config = config
|
||||||
snap.sigcache = sigcache
|
snap.sigcache = sigcache
|
||||||
snap.ethAPI = ethAPI
|
snap.ethAPI = ethAPI
|
||||||
|
|
@ -83,6 +80,7 @@ func (s *Snapshot) store(db ethdb.Database) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.Put(append([]byte("bor-"), s.Hash[:]...), blob)
|
return db.Put(append([]byte("bor-"), s.Hash[:]...), blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,6 +113,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
||||||
return nil, errOutOfRangeChain
|
return nil, errOutOfRangeChain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if headers[0].Number.Uint64() != s.Number+1 {
|
if headers[0].Number.Uint64() != s.Number+1 {
|
||||||
return nil, errOutOfRangeChain
|
return nil, errOutOfRangeChain
|
||||||
}
|
}
|
||||||
|
|
@ -126,7 +125,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
|
|
||||||
// Delete the oldest signer from the recent list to allow it signing again
|
// Delete the oldest signer from the recent list to allow it signing again
|
||||||
if number >= s.config.Sprint && number-s.config.Sprint >= 0 {
|
if number >= s.config.Sprint {
|
||||||
delete(snap.Recents, number-s.config.Sprint)
|
delete(snap.Recents, number-s.config.Sprint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,6 +152,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
||||||
if err := validateHeaderExtraField(header.Extra); err != nil {
|
if err := validateHeaderExtraField(header.Extra); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal]
|
validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal]
|
||||||
|
|
||||||
// get validators from headers and use that for new validator set
|
// get validators from headers and use that for new validator set
|
||||||
|
|
@ -162,6 +162,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
||||||
snap.ValidatorSet = v
|
snap.ValidatorSet = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
snap.Number += uint64(len(headers))
|
snap.Number += uint64(len(headers))
|
||||||
snap.Hash = headers[len(headers)-1].Hash()
|
snap.Hash = headers[len(headers)-1].Hash()
|
||||||
|
|
||||||
|
|
@ -173,10 +174,13 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error)
|
||||||
validators := s.ValidatorSet.Validators
|
validators := s.ValidatorSet.Validators
|
||||||
proposer := s.ValidatorSet.GetProposer().Address
|
proposer := s.ValidatorSet.GetProposer().Address
|
||||||
proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer)
|
proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer)
|
||||||
|
|
||||||
if proposerIndex == -1 {
|
if proposerIndex == -1 {
|
||||||
return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()}
|
return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()}
|
||||||
}
|
}
|
||||||
|
|
||||||
signerIndex, _ := s.ValidatorSet.GetByAddress(signer)
|
signerIndex, _ := s.ValidatorSet.GetByAddress(signer)
|
||||||
|
|
||||||
if signerIndex == -1 {
|
if signerIndex == -1 {
|
||||||
return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()}
|
return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()}
|
||||||
}
|
}
|
||||||
|
|
@ -187,6 +191,7 @@ func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error)
|
||||||
tempIndex = tempIndex + len(validators)
|
tempIndex = tempIndex + len(validators)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tempIndex - proposerIndex, nil
|
return tempIndex - proposerIndex, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -196,13 +201,14 @@ func (s *Snapshot) signers() []common.Address {
|
||||||
for _, sig := range s.ValidatorSet.Validators {
|
for _, sig := range s.ValidatorSet.Validators {
|
||||||
sigs = append(sigs, sig.Address)
|
sigs = append(sigs, sig.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sigs
|
return sigs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Difficulty returns the difficulty for a particular signer at the current snapshot number
|
// Difficulty returns the difficulty for a particular signer at the current snapshot number
|
||||||
func (s *Snapshot) Difficulty(signer common.Address) uint64 {
|
func (s *Snapshot) Difficulty(signer common.Address) uint64 {
|
||||||
// if signer is empty
|
// if signer is empty
|
||||||
if bytes.Compare(signer.Bytes(), common.Address{}.Bytes()) == 0 {
|
if bytes.Equal(signer.Bytes(), common.Address{}.Bytes()) {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) {
|
func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
validators := buildRandomValidatorSet(numVals)
|
validators := buildRandomValidatorSet(numVals)
|
||||||
validatorSet := NewValidatorSet(validators)
|
validatorSet := NewValidatorSet(validators)
|
||||||
snap := Snapshot{
|
snap := Snapshot{
|
||||||
|
|
@ -25,17 +27,22 @@ func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) {
|
||||||
// proposer is signer
|
// proposer is signer
|
||||||
signer := validatorSet.Proposer.Address
|
signer := validatorSet.Proposer.Address
|
||||||
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, 0, successionNumber)
|
assert.Equal(t, 0, successionNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) {
|
func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
validators := buildRandomValidatorSet(numVals)
|
validators := buildRandomValidatorSet(numVals)
|
||||||
|
|
||||||
// sort validators by address, which is what NewValidatorSet also does
|
// sort validators by address, which is what NewValidatorSet also does
|
||||||
sort.Sort(ValidatorsByAddress(validators))
|
sort.Sort(ValidatorsByAddress(validators))
|
||||||
|
|
||||||
proposerIndex := 32
|
proposerIndex := 32
|
||||||
signerIndex := 56
|
signerIndex := 56
|
||||||
// give highest ProposerPriority to a particular val, so that they become the proposer
|
// give highest ProposerPriority to a particular val, so that they become the proposer
|
||||||
|
|
@ -47,13 +54,17 @@ func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) {
|
||||||
// choose a signer at an index greater than proposer index
|
// choose a signer at an index greater than proposer index
|
||||||
signer := snap.ValidatorSet.Validators[signerIndex].Address
|
signer := snap.ValidatorSet.Validators[signerIndex].Address
|
||||||
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, signerIndex-proposerIndex, successionNumber)
|
assert.Equal(t, signerIndex-proposerIndex, successionNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) {
|
func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
validators := buildRandomValidatorSet(numVals)
|
validators := buildRandomValidatorSet(numVals)
|
||||||
proposerIndex := 98
|
proposerIndex := 98
|
||||||
signerIndex := 11
|
signerIndex := 11
|
||||||
|
|
@ -66,13 +77,17 @@ func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) {
|
||||||
// choose a signer at an index greater than proposer index
|
// choose a signer at an index greater than proposer index
|
||||||
signer := snap.ValidatorSet.Validators[signerIndex].Address
|
signer := snap.ValidatorSet.Validators[signerIndex].Address
|
||||||
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err)
|
t.Fatalf("%s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, signerIndex+numVals-proposerIndex, successionNumber)
|
assert.Equal(t, signerIndex+numVals-proposerIndex, successionNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) {
|
func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
validators := buildRandomValidatorSet(numVals)
|
validators := buildRandomValidatorSet(numVals)
|
||||||
snap := Snapshot{
|
snap := Snapshot{
|
||||||
ValidatorSet: NewValidatorSet(validators),
|
ValidatorSet: NewValidatorSet(validators),
|
||||||
|
|
@ -89,6 +104,8 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
|
func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
validators := buildRandomValidatorSet(numVals)
|
validators := buildRandomValidatorSet(numVals)
|
||||||
snap := Snapshot{
|
snap := Snapshot{
|
||||||
ValidatorSet: NewValidatorSet(validators),
|
ValidatorSet: NewValidatorSet(validators),
|
||||||
|
|
@ -101,9 +118,12 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) {
|
||||||
assert.Equal(t, dummySignerAddress.Bytes(), e.Signer)
|
assert.Equal(t, dummySignerAddress.Bytes(), e.Signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint: unparam
|
||||||
func buildRandomValidatorSet(numVals int) []*Validator {
|
func buildRandomValidatorSet(numVals int) []*Validator {
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
|
|
||||||
validators := make([]*Validator, numVals)
|
validators := make([]*Validator, numVals)
|
||||||
|
|
||||||
for i := 0; i < numVals; i++ {
|
for i := 0; i < numVals; i++ {
|
||||||
validators[i] = &Validator{
|
validators[i] = &Validator{
|
||||||
Address: randomAddress(),
|
Address: randomAddress(),
|
||||||
|
|
@ -114,11 +134,13 @@ func buildRandomValidatorSet(numVals int) []*Validator {
|
||||||
|
|
||||||
// sort validators by address, which is what NewValidatorSet also does
|
// sort validators by address, which is what NewValidatorSet also does
|
||||||
sort.Sort(ValidatorsByAddress(validators))
|
sort.Sort(ValidatorsByAddress(validators))
|
||||||
|
|
||||||
return validators
|
return validators
|
||||||
}
|
}
|
||||||
|
|
||||||
func randomAddress() common.Address {
|
func randomAddress() common.Address {
|
||||||
bytes := make([]byte, 32)
|
bytes := make([]byte, 32)
|
||||||
rand.Read(bytes)
|
rand.Read(bytes)
|
||||||
|
|
||||||
return common.BytesToAddress(bytes)
|
return common.BytesToAddress(bytes)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,12 @@ func (v *Validator) Cmp(other *Validator) *Validator {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return other
|
return other
|
||||||
}
|
}
|
||||||
|
|
||||||
if other == nil {
|
if other == nil {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint:nestif
|
||||||
if v.ProposerPriority > other.ProposerPriority {
|
if v.ProposerPriority > other.ProposerPriority {
|
||||||
return v
|
return v
|
||||||
} else if v.ProposerPriority < other.ProposerPriority {
|
} else if v.ProposerPriority < other.ProposerPriority {
|
||||||
|
|
@ -66,6 +69,7 @@ func (v *Validator) String() string {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return "nil-Validator"
|
return "nil-Validator"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("Validator{%v Power:%v Priority:%v}",
|
return fmt.Sprintf("Validator{%v Power:%v Priority:%v}",
|
||||||
v.Address.Hex(),
|
v.Address.Hex(),
|
||||||
v.VotingPower,
|
v.VotingPower,
|
||||||
|
|
@ -87,6 +91,7 @@ func (v *Validator) HeaderBytes() []byte {
|
||||||
result := make([]byte, 40)
|
result := make([]byte, 40)
|
||||||
copy(result[:20], v.Address.Bytes())
|
copy(result[:20], v.Address.Bytes())
|
||||||
copy(result[20:], v.PowerBytes())
|
copy(result[20:], v.PowerBytes())
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,6 +100,7 @@ func (v *Validator) PowerBytes() []byte {
|
||||||
powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes()
|
powerBytes := big.NewInt(0).SetInt64(v.VotingPower).Bytes()
|
||||||
result := make([]byte, 20)
|
result := make([]byte, 20)
|
||||||
copy(result[20-len(powerBytes):], powerBytes)
|
copy(result[20-len(powerBytes):], powerBytes)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,6 +120,7 @@ func ParseValidators(validatorsBytes []byte) ([]*Validator, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]*Validator, len(validatorsBytes)/40)
|
result := make([]*Validator, len(validatorsBytes)/40)
|
||||||
|
|
||||||
for i := 0; i < len(validatorsBytes); i += 40 {
|
for i := 0; i < len(validatorsBytes); i += 40 {
|
||||||
address := make([]byte, 20)
|
address := make([]byte, 20)
|
||||||
power := make([]byte, 20)
|
power := make([]byte, 20)
|
||||||
|
|
@ -142,6 +149,7 @@ func SortMinimalValByAddress(a []MinimalVal) []MinimalVal {
|
||||||
sort.Slice(a, func(i, j int) bool {
|
sort.Slice(a, func(i, j int) bool {
|
||||||
return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0
|
return bytes.Compare(a[i].Signer.Bytes(), a[j].Signer.Bytes()) < 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,5 +158,6 @@ func ValidatorsToMinimalValidators(vals []Validator) (minVals []MinimalVal) {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
minVals = append(minVals, val.MinimalVal())
|
minVals = append(minVals, val.MinimalVal())
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,12 +56,15 @@ type ValidatorSet struct {
|
||||||
func NewValidatorSet(valz []*Validator) *ValidatorSet {
|
func NewValidatorSet(valz []*Validator) *ValidatorSet {
|
||||||
vals := &ValidatorSet{}
|
vals := &ValidatorSet{}
|
||||||
err := vals.updateWithChangeSet(valz, false)
|
err := vals.updateWithChangeSet(valz, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("cannot create validator set: %s", err))
|
panic(fmt.Sprintf("cannot create validator set: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(valz) > 0 {
|
if len(valz) > 0 {
|
||||||
vals.IncrementProposerPriority(1)
|
vals.IncrementProposerPriority(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return vals
|
return vals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,9 +75,10 @@ func (vals *ValidatorSet) IsNilOrEmpty() bool {
|
||||||
|
|
||||||
// Increment ProposerPriority and update the proposer on a copy, and return it.
|
// Increment ProposerPriority and update the proposer on a copy, and return it.
|
||||||
func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet {
|
func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet {
|
||||||
copy := vals.Copy()
|
validatorCopy := vals.Copy()
|
||||||
copy.IncrementProposerPriority(times)
|
validatorCopy.IncrementProposerPriority(times)
|
||||||
return copy
|
|
||||||
|
return validatorCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementProposerPriority increments ProposerPriority of each validator and updates the
|
// IncrementProposerPriority increments ProposerPriority of each validator and updates the
|
||||||
|
|
@ -84,6 +88,7 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int) {
|
||||||
if vals.IsNilOrEmpty() {
|
if vals.IsNilOrEmpty() {
|
||||||
panic("empty validator set")
|
panic("empty validator set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if times <= 0 {
|
if times <= 0 {
|
||||||
panic("Cannot call IncrementProposerPriority with non-positive times")
|
panic("Cannot call IncrementProposerPriority with non-positive times")
|
||||||
}
|
}
|
||||||
|
|
@ -120,6 +125,7 @@ func (vals *ValidatorSet) RescalePriorities(diffMax int64) {
|
||||||
// NOTE: This may make debugging priority issues easier as well.
|
// NOTE: This may make debugging priority issues easier as well.
|
||||||
diff := computeMaxMinPriorityDiff(vals)
|
diff := computeMaxMinPriorityDiff(vals)
|
||||||
ratio := (diff + diffMax - 1) / diffMax
|
ratio := (diff + diffMax - 1) / diffMax
|
||||||
|
|
||||||
if diff > diffMax {
|
if diff > diffMax {
|
||||||
for _, val := range vals.Validators {
|
for _, val := range vals.Validators {
|
||||||
val.ProposerPriority = val.ProposerPriority / ratio
|
val.ProposerPriority = val.ProposerPriority / ratio
|
||||||
|
|
@ -145,10 +151,13 @@ func (vals *ValidatorSet) incrementProposerPriority() *Validator {
|
||||||
func (vals *ValidatorSet) computeAvgProposerPriority() int64 {
|
func (vals *ValidatorSet) computeAvgProposerPriority() int64 {
|
||||||
n := int64(len(vals.Validators))
|
n := int64(len(vals.Validators))
|
||||||
sum := big.NewInt(0)
|
sum := big.NewInt(0)
|
||||||
|
|
||||||
for _, val := range vals.Validators {
|
for _, val := range vals.Validators {
|
||||||
sum.Add(sum, big.NewInt(val.ProposerPriority))
|
sum.Add(sum, big.NewInt(val.ProposerPriority))
|
||||||
}
|
}
|
||||||
|
|
||||||
avg := sum.Div(sum, big.NewInt(n))
|
avg := sum.Div(sum, big.NewInt(n))
|
||||||
|
|
||||||
if avg.IsInt64() {
|
if avg.IsInt64() {
|
||||||
return avg.Int64()
|
return avg.Int64()
|
||||||
}
|
}
|
||||||
|
|
@ -162,17 +171,22 @@ func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 {
|
||||||
if vals.IsNilOrEmpty() {
|
if vals.IsNilOrEmpty() {
|
||||||
panic("empty validator set")
|
panic("empty validator set")
|
||||||
}
|
}
|
||||||
|
|
||||||
max := int64(math.MinInt64)
|
max := int64(math.MinInt64)
|
||||||
min := int64(math.MaxInt64)
|
min := int64(math.MaxInt64)
|
||||||
|
|
||||||
for _, v := range vals.Validators {
|
for _, v := range vals.Validators {
|
||||||
if v.ProposerPriority < min {
|
if v.ProposerPriority < min {
|
||||||
min = v.ProposerPriority
|
min = v.ProposerPriority
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.ProposerPriority > max {
|
if v.ProposerPriority > max {
|
||||||
max = v.ProposerPriority
|
max = v.ProposerPriority
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diff := max - min
|
diff := max - min
|
||||||
|
|
||||||
if diff < 0 {
|
if diff < 0 {
|
||||||
return -1 * diff
|
return -1 * diff
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -185,6 +199,7 @@ func (vals *ValidatorSet) getValWithMostPriority() *Validator {
|
||||||
for _, val := range vals.Validators {
|
for _, val := range vals.Validators {
|
||||||
res = res.Cmp(val)
|
res = res.Cmp(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,7 +207,9 @@ func (vals *ValidatorSet) shiftByAvgProposerPriority() {
|
||||||
if vals.IsNilOrEmpty() {
|
if vals.IsNilOrEmpty() {
|
||||||
panic("empty validator set")
|
panic("empty validator set")
|
||||||
}
|
}
|
||||||
|
|
||||||
avgProposerPriority := vals.computeAvgProposerPriority()
|
avgProposerPriority := vals.computeAvgProposerPriority()
|
||||||
|
|
||||||
for _, val := range vals.Validators {
|
for _, val := range vals.Validators {
|
||||||
val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority)
|
val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority)
|
||||||
}
|
}
|
||||||
|
|
@ -203,10 +220,13 @@ func validatorListCopy(valsList []*Validator) []*Validator {
|
||||||
if valsList == nil {
|
if valsList == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
valsCopy := make([]*Validator, len(valsList))
|
valsCopy := make([]*Validator, len(valsList))
|
||||||
|
|
||||||
for i, val := range valsList {
|
for i, val := range valsList {
|
||||||
valsCopy[i] = val.Copy()
|
valsCopy[i] = val.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
return valsCopy
|
return valsCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,6 +245,7 @@ func (vals *ValidatorSet) HasAddress(address []byte) bool {
|
||||||
idx := sort.Search(len(vals.Validators), func(i int) bool {
|
idx := sort.Search(len(vals.Validators), func(i int) bool {
|
||||||
return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0
|
return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0
|
||||||
})
|
})
|
||||||
|
|
||||||
return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address)
|
return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,6 +258,7 @@ func (vals *ValidatorSet) GetByAddress(address common.Address) (index int, val *
|
||||||
if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) {
|
if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) {
|
||||||
return idx, vals.Validators[idx].Copy()
|
return idx, vals.Validators[idx].Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1, nil
|
return -1, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +269,9 @@ func (vals *ValidatorSet) GetByIndex(index int) (address []byte, val *Validator)
|
||||||
if index < 0 || index >= len(vals.Validators) {
|
if index < 0 || index >= len(vals.Validators) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
val = vals.Validators[index]
|
val = vals.Validators[index]
|
||||||
|
|
||||||
return val.Address.Bytes(), val.Copy()
|
return val.Address.Bytes(), val.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +282,6 @@ func (vals *ValidatorSet) Size() int {
|
||||||
|
|
||||||
// Force recalculation of the set's total voting power.
|
// Force recalculation of the set's total voting power.
|
||||||
func (vals *ValidatorSet) updateTotalVotingPower() error {
|
func (vals *ValidatorSet) updateTotalVotingPower() error {
|
||||||
|
|
||||||
sum := int64(0)
|
sum := int64(0)
|
||||||
for _, val := range vals.Validators {
|
for _, val := range vals.Validators {
|
||||||
// mind overflow
|
// mind overflow
|
||||||
|
|
@ -267,7 +290,9 @@ func (vals *ValidatorSet) updateTotalVotingPower() error {
|
||||||
return &TotalVotingPowerExceededError{sum, vals.Validators}
|
return &TotalVotingPowerExceededError{sum, vals.Validators}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vals.totalVotingPower = sum
|
vals.totalVotingPower = sum
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,11 +301,13 @@ func (vals *ValidatorSet) updateTotalVotingPower() error {
|
||||||
func (vals *ValidatorSet) TotalVotingPower() int64 {
|
func (vals *ValidatorSet) TotalVotingPower() int64 {
|
||||||
if vals.totalVotingPower == 0 {
|
if vals.totalVotingPower == 0 {
|
||||||
log.Info("invoking updateTotalVotingPower before returning it")
|
log.Info("invoking updateTotalVotingPower before returning it")
|
||||||
|
|
||||||
if err := vals.updateTotalVotingPower(); err != nil {
|
if err := vals.updateTotalVotingPower(); err != nil {
|
||||||
// Can/should we do better?
|
// Can/should we do better?
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vals.totalVotingPower
|
return vals.totalVotingPower
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -290,9 +317,11 @@ func (vals *ValidatorSet) GetProposer() (proposer *Validator) {
|
||||||
if len(vals.Validators) == 0 {
|
if len(vals.Validators) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if vals.Proposer == nil {
|
if vals.Proposer == nil {
|
||||||
vals.Proposer = vals.findProposer()
|
vals.Proposer = vals.findProposer()
|
||||||
}
|
}
|
||||||
|
|
||||||
return vals.Proposer.Copy()
|
return vals.Proposer.Copy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,6 +332,7 @@ func (vals *ValidatorSet) findProposer() *Validator {
|
||||||
proposer = proposer.Cmp(val)
|
proposer = proposer.Cmp(val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return proposer
|
return proposer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -343,6 +373,7 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
|
||||||
|
|
||||||
removals = make([]*Validator, 0, len(changes))
|
removals = make([]*Validator, 0, len(changes))
|
||||||
updates = make([]*Validator, 0, len(changes))
|
updates = make([]*Validator, 0, len(changes))
|
||||||
|
|
||||||
var prevAddr common.Address
|
var prevAddr common.Address
|
||||||
|
|
||||||
// Scan changes by address and append valid validators to updates or removals lists.
|
// Scan changes by address and append valid validators to updates or removals lists.
|
||||||
|
|
@ -351,22 +382,27 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
|
||||||
err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes)
|
err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if valUpdate.VotingPower < 0 {
|
if valUpdate.VotingPower < 0 {
|
||||||
err = fmt.Errorf("voting power can't be negative: %v", valUpdate)
|
err = fmt.Errorf("voting power can't be negative: %v", valUpdate)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if valUpdate.VotingPower > MaxTotalVotingPower {
|
if valUpdate.VotingPower > MaxTotalVotingPower {
|
||||||
err = fmt.Errorf("to prevent clipping/ overflow, voting power can't be higher than %v: %v ",
|
err = fmt.Errorf("to prevent clipping/ overflow, voting power can't be higher than %v: %v ",
|
||||||
MaxTotalVotingPower, valUpdate)
|
MaxTotalVotingPower, valUpdate)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if valUpdate.VotingPower == 0 {
|
if valUpdate.VotingPower == 0 {
|
||||||
removals = append(removals, valUpdate)
|
removals = append(removals, valUpdate)
|
||||||
} else {
|
} else {
|
||||||
updates = append(updates, valUpdate)
|
updates = append(updates, valUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
prevAddr = valUpdate.Address
|
prevAddr = valUpdate.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
return updates, removals, err
|
return updates, removals, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,12 +418,12 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e
|
||||||
// by processChanges for duplicates and invalid values.
|
// by processChanges for duplicates and invalid values.
|
||||||
// No changes are made to the validator set 'vals'.
|
// No changes are made to the validator set 'vals'.
|
||||||
func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) {
|
func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) {
|
||||||
|
|
||||||
updatedTotalVotingPower = vals.TotalVotingPower()
|
updatedTotalVotingPower = vals.TotalVotingPower()
|
||||||
|
|
||||||
for _, valUpdate := range updates {
|
for _, valUpdate := range updates {
|
||||||
address := valUpdate.Address
|
address := valUpdate.Address
|
||||||
_, val := vals.GetByAddress(address)
|
_, val := vals.GetByAddress(address)
|
||||||
|
|
||||||
if val == nil {
|
if val == nil {
|
||||||
// New validator, add its voting power the the total.
|
// New validator, add its voting power the the total.
|
||||||
updatedTotalVotingPower += valUpdate.VotingPower
|
updatedTotalVotingPower += valUpdate.VotingPower
|
||||||
|
|
@ -396,11 +432,14 @@ func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVoting
|
||||||
// Updated validator, add the difference in power to the total.
|
// Updated validator, add the difference in power to the total.
|
||||||
updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower
|
updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower
|
||||||
}
|
}
|
||||||
|
|
||||||
overflow := updatedTotalVotingPower > MaxTotalVotingPower
|
overflow := updatedTotalVotingPower > MaxTotalVotingPower
|
||||||
|
|
||||||
if overflow {
|
if overflow {
|
||||||
err = fmt.Errorf(
|
err = fmt.Errorf(
|
||||||
"failed to add/update validator %v, total voting power would exceed the max allowed %v",
|
"failed to add/update validator %v, total voting power would exceed the max allowed %v",
|
||||||
valUpdate, MaxTotalVotingPower)
|
valUpdate, MaxTotalVotingPower)
|
||||||
|
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -414,10 +453,10 @@ func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVoting
|
||||||
// 'updates' parameter must be a list of unique validators to be added or updated.
|
// 'updates' parameter must be a list of unique validators to be added or updated.
|
||||||
// No changes are made to the validator set 'vals'.
|
// No changes are made to the validator set 'vals'.
|
||||||
func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) {
|
func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotalVotingPower int64) {
|
||||||
|
|
||||||
for _, valUpdate := range updates {
|
for _, valUpdate := range updates {
|
||||||
address := valUpdate.Address
|
address := valUpdate.Address
|
||||||
_, val := vals.GetByAddress(address)
|
_, val := vals.GetByAddress(address)
|
||||||
|
|
||||||
if val == nil {
|
if val == nil {
|
||||||
// add val
|
// add val
|
||||||
// Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't
|
// Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't
|
||||||
|
|
@ -432,7 +471,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal
|
||||||
valUpdate.ProposerPriority = val.ProposerPriority
|
valUpdate.ProposerPriority = val.ProposerPriority
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merges the vals' validator list with the updates list.
|
// Merges the vals' validator list with the updates list.
|
||||||
|
|
@ -440,7 +478,6 @@ func computeNewPriorities(updates []*Validator, vals *ValidatorSet, updatedTotal
|
||||||
// Expects updates to be a list of updates sorted by address with no duplicates or errors,
|
// Expects updates to be a list of updates sorted by address with no duplicates or errors,
|
||||||
// must have been validated with verifyUpdates() and priorities computed with computeNewPriorities().
|
// must have been validated with verifyUpdates() and priorities computed with computeNewPriorities().
|
||||||
func (vals *ValidatorSet) applyUpdates(updates []*Validator) {
|
func (vals *ValidatorSet) applyUpdates(updates []*Validator) {
|
||||||
|
|
||||||
existing := vals.Validators
|
existing := vals.Validators
|
||||||
merged := make([]*Validator, len(existing)+len(updates))
|
merged := make([]*Validator, len(existing)+len(updates))
|
||||||
i := 0
|
i := 0
|
||||||
|
|
@ -478,24 +515,25 @@ func (vals *ValidatorSet) applyUpdates(updates []*Validator) {
|
||||||
// Checks that the validators to be removed are part of the validator set.
|
// Checks that the validators to be removed are part of the validator set.
|
||||||
// No changes are made to the validator set 'vals'.
|
// No changes are made to the validator set 'vals'.
|
||||||
func verifyRemovals(deletes []*Validator, vals *ValidatorSet) error {
|
func verifyRemovals(deletes []*Validator, vals *ValidatorSet) error {
|
||||||
|
|
||||||
for _, valUpdate := range deletes {
|
for _, valUpdate := range deletes {
|
||||||
address := valUpdate.Address
|
address := valUpdate.Address
|
||||||
_, val := vals.GetByAddress(address)
|
_, val := vals.GetByAddress(address)
|
||||||
|
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return fmt.Errorf("failed to find validator %X to remove", address)
|
return fmt.Errorf("failed to find validator %X to remove", address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(deletes) > len(vals.Validators) {
|
if len(deletes) > len(vals.Validators) {
|
||||||
panic("more deletes than validators")
|
panic("more deletes than validators")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the validators specified in 'deletes' from validator set 'vals'.
|
// Removes the validators specified in 'deletes' from validator set 'vals'.
|
||||||
// Should not fail as verification has been done before.
|
// Should not fail as verification has been done before.
|
||||||
func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
|
func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
|
||||||
|
|
||||||
existing := vals.Validators
|
existing := vals.Validators
|
||||||
|
|
||||||
merged := make([]*Validator, len(existing)-len(deletes))
|
merged := make([]*Validator, len(existing)-len(deletes))
|
||||||
|
|
@ -509,6 +547,7 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
|
||||||
merged[i] = existing[0]
|
merged[i] = existing[0]
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
existing = existing[1:]
|
existing = existing[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -526,7 +565,6 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) {
|
||||||
// are not allowed and will trigger an error if present in 'changes'.
|
// are not allowed and will trigger an error if present in 'changes'.
|
||||||
// The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet().
|
// The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet().
|
||||||
func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error {
|
func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error {
|
||||||
|
|
||||||
if len(changes) <= 0 {
|
if len(changes) <= 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -596,19 +634,19 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error {
|
||||||
|
|
||||||
func IsErrTooMuchChange(err error) bool {
|
func IsErrTooMuchChange(err error) bool {
|
||||||
switch err.(type) {
|
switch err.(type) {
|
||||||
case errTooMuchChange:
|
case tooMuchChangeError:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type errTooMuchChange struct {
|
type tooMuchChangeError struct {
|
||||||
got int64
|
got int64
|
||||||
needed int64
|
needed int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e errTooMuchChange) Error() string {
|
func (e tooMuchChangeError) Error() string {
|
||||||
return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed)
|
return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -622,11 +660,14 @@ func (vals *ValidatorSet) StringIndented(indent string) string {
|
||||||
if vals == nil {
|
if vals == nil {
|
||||||
return "nil-ValidatorSet"
|
return "nil-ValidatorSet"
|
||||||
}
|
}
|
||||||
|
|
||||||
var valStrings []string
|
var valStrings []string
|
||||||
|
|
||||||
vals.Iterate(func(index int, val *Validator) bool {
|
vals.Iterate(func(index int, val *Validator) bool {
|
||||||
valStrings = append(valStrings, val.String())
|
valStrings = append(valStrings, val.String())
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
return fmt.Sprintf(`ValidatorSet{
|
return fmt.Sprintf(`ValidatorSet{
|
||||||
%s Proposer: %v
|
%s Proposer: %v
|
||||||
%s Validators:
|
%s Validators:
|
||||||
|
|
@ -636,7 +677,6 @@ func (vals *ValidatorSet) StringIndented(indent string) string {
|
||||||
indent,
|
indent,
|
||||||
indent, strings.Join(valStrings, "\n"+indent+" "),
|
indent, strings.Join(valStrings, "\n"+indent+" "),
|
||||||
indent)
|
indent)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
@ -668,6 +708,7 @@ func safeAdd(a, b int64) (int64, bool) {
|
||||||
} else if b < 0 && a < math.MinInt64-b {
|
} else if b < 0 && a < math.MinInt64-b {
|
||||||
return -1, true
|
return -1, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return a + b, false
|
return a + b, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -677,6 +718,7 @@ func safeSub(a, b int64) (int64, bool) {
|
||||||
} else if b < 0 && a > math.MaxInt64+b {
|
} else if b < 0 && a > math.MaxInt64+b {
|
||||||
return -1, true
|
return -1, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return a - b, false
|
return a - b, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -686,8 +728,10 @@ func safeAddClip(a, b int64) int64 {
|
||||||
if b < 0 {
|
if b < 0 {
|
||||||
return math.MinInt64
|
return math.MinInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
return math.MaxInt64
|
return math.MaxInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -697,7 +741,9 @@ func safeSubClip(a, b int64) int64 {
|
||||||
if b > 0 {
|
if b > 0 {
|
||||||
return math.MinInt64
|
return math.MinInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
return math.MaxInt64
|
return math.MaxInt64
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue