mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 07:36:44 +00:00
refactor: Tests + add test for OutOfTurnSign
This commit is contained in:
parent
c27b8b7801
commit
71c3bf757c
6 changed files with 176 additions and 113 deletions
|
|
@ -114,10 +114,6 @@ var (
|
|||
// errInvalidDifficulty is returned if the difficulty of a block neither 1 or 2.
|
||||
errInvalidDifficulty = errors.New("invalid difficulty")
|
||||
|
||||
// errWrongDifficulty is returned if the difficulty of a block doesn't match the
|
||||
// turn of the signer.
|
||||
errWrongDifficulty = errors.New("wrong difficulty")
|
||||
|
||||
// ErrInvalidTimestamp is returned if the timestamp of a block is lower than
|
||||
// the previous block's timestamp + the minimum block period.
|
||||
ErrInvalidTimestamp = errors.New("invalid timestamp")
|
||||
|
|
@ -126,9 +122,6 @@ var (
|
|||
// be modified via out-of-range or non-contiguous headers.
|
||||
errOutOfRangeChain = errors.New("out of range or non-contiguous chain")
|
||||
|
||||
// errUnauthorizedSigner is returned if a header is signed by a non-authorized entity.
|
||||
errUnauthorizedSigner = errors.New("unauthorized signer")
|
||||
|
||||
// errRecentlySigned is returned if a header is signed by an authorized entity
|
||||
// that already signed a header recently, thus is temporarily not allowed to.
|
||||
errRecentlySigned = errors.New("recently signed")
|
||||
|
|
@ -200,13 +193,6 @@ func encodeSigHeader(w io.Writer, header *types.Header) {
|
|||
}
|
||||
}
|
||||
|
||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty
|
||||
// that a new block should have based on the previous blocks in the chain and the
|
||||
// current signer.
|
||||
func CalcDifficulty(snap *Snapshot, signer common.Address, sprint uint64) *big.Int {
|
||||
return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, sprint))
|
||||
}
|
||||
|
||||
// CalcProducerDelay is the block delay algorithm based on block time, period, producerDelay and turn-ness of a signer
|
||||
func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint64 {
|
||||
// When the block is the first block of the sprint, it is expected to be delayed by `producerDelay`.
|
||||
|
|
@ -580,7 +566,7 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare
|
|||
return err
|
||||
}
|
||||
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
||||
return errUnauthorizedSigner
|
||||
return &UnauthorizedSignerError{number, signer.Bytes()}
|
||||
}
|
||||
|
||||
succession, err := snap.GetSignerSuccessionNumber(signer)
|
||||
|
|
@ -601,9 +587,9 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare
|
|||
|
||||
// Ensure that the difficulty corresponds to the turn-ness of the signer
|
||||
if !c.fakeDiff {
|
||||
difficulty := snap.inturn(header.Number.Uint64(), signer, c.config.Sprint)
|
||||
difficulty := snap.Difficulty(signer)
|
||||
if header.Difficulty.Uint64() != difficulty {
|
||||
return errWrongDifficulty
|
||||
return &WrongDifficultyError{number, difficulty, header.Difficulty.Uint64(), signer.Bytes()}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -625,7 +611,7 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
|||
}
|
||||
|
||||
// Set the correct difficulty
|
||||
header.Difficulty = CalcDifficulty(snap, c.signer, c.config.Sprint)
|
||||
header.Difficulty = new(big.Int).SetUint64(snap.Difficulty(c.signer))
|
||||
|
||||
// Ensure the extra data has all it's components
|
||||
if len(header.Extra) < extraVanity {
|
||||
|
|
@ -659,10 +645,15 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
|||
return consensus.ErrUnknownAncestor
|
||||
}
|
||||
|
||||
succession, err := snap.GetSignerSuccessionNumber(c.signer)
|
||||
if err != nil {
|
||||
return err
|
||||
var succession int
|
||||
// if signer is not empty
|
||||
if bytes.Compare(c.signer.Bytes(), common.Address{}.Bytes()) != 0 {
|
||||
succession, err = snap.GetSignerSuccessionNumber(c.signer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
header.Time = parent.Time + CalcProducerDelay(number, succession, c.config)
|
||||
if header.Time < uint64(time.Now().Unix()) {
|
||||
header.Time = uint64(time.Now().Unix())
|
||||
|
|
@ -764,7 +755,7 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan
|
|||
|
||||
// Bail out if we're unauthorized to sign a block
|
||||
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
||||
return errUnauthorizedSigner
|
||||
return &UnauthorizedSignerError{number, signer.Bytes()}
|
||||
}
|
||||
|
||||
successionNumber, err := snap.GetSignerSuccessionNumber(signer)
|
||||
|
|
@ -852,7 +843,7 @@ func (c *Bor) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *t
|
|||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return CalcDifficulty(snap, c.signer, c.config.Sprint)
|
||||
return new(big.Int).SetUint64(snap.Difficulty(c.signer))
|
||||
}
|
||||
|
||||
// SealHash returns the hash of a block prior to it being sealed.
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/maticnetwork/bor/common"
|
||||
"github.com/maticnetwork/bor/consensus/bor"
|
||||
"github.com/maticnetwork/bor/core/rawdb"
|
||||
"github.com/maticnetwork/bor/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/maticnetwork/bor/core/types"
|
||||
|
|
@ -28,23 +29,17 @@ func TestCommitSpan(t *testing.T) {
|
|||
_bor.SetHeimdallClient(h)
|
||||
|
||||
db := init.ethereum.ChainDb()
|
||||
statedb, err := chain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
_key, _ := hex.DecodeString(privKey)
|
||||
|
||||
block := init.genesis.ToBlock(db)
|
||||
// Insert sprintSize # of blocks so that span is fetched at the start of a new sprint
|
||||
for i := uint64(1); i <= sprintSize; i++ {
|
||||
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
|
||||
block = insertNewBlock(t, _bor, chain, header, statedb, _key)
|
||||
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
||||
insertNewBlock(t, chain, block)
|
||||
}
|
||||
|
||||
// FetchWithRetry is invoked 2 times
|
||||
// 1. bor.FinalizeAndAssemble to prepare a new block when calling insertNewBlock
|
||||
// 1. bor.FinalizeAndAssemble to prepare a new block when calling buildNextBlock
|
||||
// 2. bor.Finalize via(bc.insertChain => bc.processor.Process)
|
||||
assert.True(t, h.AssertNumberOfCalls(t, "FetchWithRetry", 2))
|
||||
assert.True(t, h.AssertCalled(t, "FetchWithRetry", "bor", "span", "1"))
|
||||
validators, err := _bor.GetCurrentValidators(sprintSize, 256) // new span starts at 256
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
|
|
@ -88,16 +83,11 @@ func TestIsValidatorAction(t *testing.T) {
|
|||
_bor.SetHeimdallClient(h)
|
||||
|
||||
db := init.ethereum.ChainDb()
|
||||
statedb, err := chain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
_key, _ := hex.DecodeString(privKey)
|
||||
|
||||
block := init.genesis.ToBlock(db)
|
||||
|
||||
for i := uint64(1); i <= spanSize; i++ {
|
||||
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
|
||||
block = insertNewBlock(t, _bor, chain, header, statedb, _key)
|
||||
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
||||
insertNewBlock(t, chain, block)
|
||||
}
|
||||
|
||||
for _, validator := range heimdallSpan.SelectedProducers {
|
||||
|
|
@ -119,3 +109,54 @@ func TestIsValidatorAction(t *testing.T) {
|
|||
assert.True(t, _bor.IsValidatorAction(chain, _addr, tx))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutOfTurnSigning(t *testing.T) {
|
||||
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
|
||||
chain := init.ethereum.BlockChain()
|
||||
engine := init.ethereum.Engine()
|
||||
_bor := engine.(*bor.Bor)
|
||||
|
||||
res, _ := loadSpanFromFile(t)
|
||||
h := &mocks.IHeimdallClient{}
|
||||
h.On("FetchWithRetry", "bor", "span", "1").Return(res, nil)
|
||||
_bor.SetHeimdallClient(h)
|
||||
|
||||
db := init.ethereum.ChainDb()
|
||||
block := init.genesis.ToBlock(db)
|
||||
|
||||
for i := uint64(1); i < spanSize; i++ {
|
||||
block = buildNextBlock(t, _bor, chain, block, nil, init.genesis.Config.Bor)
|
||||
insertNewBlock(t, chain, block)
|
||||
}
|
||||
|
||||
// insert spanSize-th block
|
||||
// This account is one the out-of-turn validators for 1st (0-indexed) span
|
||||
signer := "c8deb0bea5c41afe8e37b4d1bd84e31adff11b09c8c96ff4b605003cce067cd9"
|
||||
signerKey, _ := hex.DecodeString(signer)
|
||||
key, _ = crypto.HexToECDSA(signer)
|
||||
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||
expectedSuccessionNumber := 2
|
||||
|
||||
block = buildNextBlock(t, _bor, chain, block, signerKey, init.genesis.Config.Bor)
|
||||
_, err := chain.InsertChain([]*types.Block{block})
|
||||
assert.Equal(t,
|
||||
*err.(*bor.BlockTooSoonError),
|
||||
bor.BlockTooSoonError{Number: spanSize, Succession: expectedSuccessionNumber})
|
||||
|
||||
expectedDifficulty := uint64(3 - expectedSuccessionNumber) // len(validators) - succession
|
||||
header := block.Header()
|
||||
header.Time += (bor.CalcProducerDelay(header.Number.Uint64(), expectedSuccessionNumber, init.genesis.Config.Bor) -
|
||||
bor.CalcProducerDelay(header.Number.Uint64(), 0, init.genesis.Config.Bor))
|
||||
sign(t, header, signerKey)
|
||||
block = types.NewBlockWithHeader(header)
|
||||
_, err = chain.InsertChain([]*types.Block{block})
|
||||
assert.Equal(t,
|
||||
*err.(*bor.WrongDifficultyError),
|
||||
bor.WrongDifficultyError{Number: spanSize, Expected: expectedDifficulty, Actual: 3, Signer: addr.Bytes()})
|
||||
|
||||
header.Difficulty = new(big.Int).SetUint64(expectedDifficulty)
|
||||
sign(t, header, signerKey)
|
||||
block = types.NewBlockWithHeader(header)
|
||||
_, err = chain.InsertChain([]*types.Block{block})
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/maticnetwork/bor/common"
|
||||
"github.com/maticnetwork/bor/consensus/bor"
|
||||
"github.com/maticnetwork/bor/core"
|
||||
"github.com/maticnetwork/bor/core/state"
|
||||
"github.com/maticnetwork/bor/core/types"
|
||||
"github.com/maticnetwork/bor/crypto"
|
||||
"github.com/maticnetwork/bor/crypto/secp256k1"
|
||||
|
|
@ -23,11 +22,19 @@ import (
|
|||
|
||||
var (
|
||||
// The genesis for tests was generated with following parameters
|
||||
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
privKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
addr = crypto.PubkeyToAddress(key.PublicKey) // 0x71562b71999873DB5b286dF957af199Ec94617F7
|
||||
validatorHeaderBytesLength = common.AddressLength + 20 // address + power
|
||||
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
|
||||
// Only this account is a validator for the 0th span
|
||||
privKey = "b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291"
|
||||
key, _ = crypto.HexToECDSA(privKey)
|
||||
addr = crypto.PubkeyToAddress(key.PublicKey) // 0x71562b71999873DB5b286dF957af199Ec94617F7
|
||||
|
||||
// This account is one the validators for 1st span (0-indexed)
|
||||
privKey2 = "9b28f36fbd67381120752d6172ecdcf10e06ab2d9a1367aac00cdcd6ac7855d3"
|
||||
key2, _ = crypto.HexToECDSA(privKey2)
|
||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey) // 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791
|
||||
|
||||
validatorHeaderBytesLength = common.AddressLength + 20 // address + power
|
||||
sprintSize uint64 = 4
|
||||
spanSize uint64 = 8
|
||||
)
|
||||
|
|
@ -88,40 +95,36 @@ func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
|
|||
}
|
||||
}
|
||||
|
||||
func insertNewBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, header *types.Header, statedb *state.StateDB, privKey []byte) *types.Block {
|
||||
_, err := _bor.FinalizeAndAssemble(chain, header, statedb, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
|
||||
sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header)), privKey)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
|
||||
|
||||
block := types.NewBlockWithHeader(header)
|
||||
func insertNewBlock(t *testing.T, chain *core.BlockChain, block *types.Block) {
|
||||
if _, err := chain.InsertChain([]*types.Block{block}); err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
return block
|
||||
}
|
||||
|
||||
func buildMinimalNextHeader(t *testing.T, block *types.Block, borConfig *params.BorConfig) *types.Header {
|
||||
func buildNextBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, block *types.Block, signer []byte, borConfig *params.BorConfig) *types.Block {
|
||||
header := block.Header()
|
||||
header.Number.Add(header.Number, big.NewInt(1))
|
||||
number := header.Number.Uint64()
|
||||
|
||||
if signer == nil {
|
||||
signer = getSignerKey(header.Number.Uint64())
|
||||
}
|
||||
|
||||
header.ParentHash = block.Hash()
|
||||
header.Time += bor.CalcProducerDelay(header.Number.Uint64(), 0, borConfig)
|
||||
header.Extra = make([]byte, 32+65) // vanity + extraSeal
|
||||
|
||||
currentValidators := []*bor.Validator{bor.NewValidator(addr, 10)}
|
||||
isSpanEnd := (header.Number.Uint64()+1)%spanSize == 0
|
||||
|
||||
isSpanEnd := (number+1)%spanSize == 0
|
||||
isSpanStart := number%spanSize == 0
|
||||
isSprintEnd := (header.Number.Uint64()+1)%sprintSize == 0
|
||||
if isSpanEnd {
|
||||
_, heimdallSpan := loadSpanFromFile(t)
|
||||
// this is to stash the validator bytes in the header
|
||||
currentValidators = heimdallSpan.ValidatorSet.Validators
|
||||
} else if header.Number.Uint64()%spanSize == 0 {
|
||||
header.Difficulty = new(big.Int).SetInt64(5)
|
||||
} else if isSpanStart {
|
||||
header.Difficulty = new(big.Int).SetInt64(3)
|
||||
}
|
||||
if isSprintEnd {
|
||||
sort.Sort(bor.ValidatorsByAddress(currentValidators))
|
||||
|
|
@ -132,13 +135,25 @@ func buildMinimalNextHeader(t *testing.T, block *types.Block, borConfig *params.
|
|||
}
|
||||
copy(header.Extra[32:], validatorBytes)
|
||||
}
|
||||
_key, _ := hex.DecodeString(privKey)
|
||||
sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header)), _key)
|
||||
|
||||
state, err := chain.State()
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
_, err = _bor.FinalizeAndAssemble(chain, header, state, nil, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
sign(t, header, signer)
|
||||
return types.NewBlockWithHeader(header)
|
||||
}
|
||||
|
||||
func sign(t *testing.T, header *types.Header, signer []byte) {
|
||||
sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header)), signer)
|
||||
if err != nil {
|
||||
t.Fatalf("%s", err)
|
||||
}
|
||||
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
|
||||
return header
|
||||
}
|
||||
|
||||
func loadSpanFromFile(t *testing.T) (*bor.ResponseWithHeight, *bor.HeimdallSpan) {
|
||||
|
|
@ -157,3 +172,14 @@ func loadSpanFromFile(t *testing.T) (*bor.ResponseWithHeight, *bor.HeimdallSpan)
|
|||
}
|
||||
return res, heimdallSpan
|
||||
}
|
||||
|
||||
func getSignerKey(number uint64) []byte {
|
||||
signerKey := privKey
|
||||
isSpanStart := number%spanSize == 0
|
||||
if isSpanStart {
|
||||
// validator set in the new span has changed
|
||||
signerKey = privKey2
|
||||
}
|
||||
_key, _ := hex.DecodeString(signerKey)
|
||||
return _key
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,85 +6,57 @@
|
|||
"end_block": 6655,
|
||||
"validator_set": {
|
||||
"validators": [{
|
||||
"ID": 3,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 10000,
|
||||
"pubKey": "0x046434e10a34ade13c4fea917346a9fd1473eac2138a0b4e2a36426871918be63188fde4edbf598457592c9a49fe3b0036dd5497079495d132e5045bf499c4bdb1",
|
||||
"signer": "0xc787af4624cb3e80ee23ae7faac0f2acea2be34c",
|
||||
"last_updated": 0,
|
||||
"accum": -40000
|
||||
}, {
|
||||
"ID": 4,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 10000,
|
||||
"pubKey": "0x04d9d09f2afc9da3cccc164e8112eb6911a63f5ede10169768f800df83cf99c73f944411e9d4fac3543b11c5f84a82e56b36cfcd34f1d065855c1e2b27af8b5247",
|
||||
"signer": "0x461295d3d9249215e758e939a150ab180950720b",
|
||||
"last_updated": 0,
|
||||
"accum": 10000
|
||||
}, {
|
||||
"ID": 5,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 10000,
|
||||
"power": 30,
|
||||
"pubKey": "0x04a36f6ed1f93acb0a38f4cacbe2467c72458ac41ce3b12b34d758205b2bc5d930a4e059462da7a0976c32fce766e1f7e8d73933ae72ac2af231fe161187743932",
|
||||
"signer": "0x836fe3e3dd0a5f77d9d5b0f67e48048aaafcd5a0",
|
||||
"signer": "0x9fB29AAc15b9A4B7F17c3385939b007540f4d791",
|
||||
"last_updated": 0,
|
||||
"accum": 10000
|
||||
}, {
|
||||
"ID": 1,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 10000,
|
||||
"power": 20,
|
||||
"pubKey": "0x04a312814042a6655c8e5ecf0c52cba0b6a6f3291c87cc42260a3c0222410c0d0d59b9139d1c56542e5df0ce2fce3a86ce13e93bd9bde0dc8ff664f8dd5294dead",
|
||||
"signer": "0x925a91f8003aaeabea6037103123b93c50b86ca3",
|
||||
"signer": "0x96C42C56fdb78294F96B0cFa33c92bed7D75F96a",
|
||||
"last_updated": 0,
|
||||
"accum": 10000
|
||||
}, {
|
||||
"ID": 2,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 10000,
|
||||
"power": 10,
|
||||
"pubKey": "0x0469536ae98030a7e83ec5ef3baffed2d05a32e31d978e58486f6bdb0fbbf240293838325116090190c0639db03f9cbd8b9aecfd269d016f46e3a2287fbf9ad232",
|
||||
"signer": "0x71562b71999873DB5b286dF957af199Ec94617F7",
|
||||
"signer": "0xc787af4624cb3e80ee23ae7faac0f2acea2be34c",
|
||||
"last_updated": 0,
|
||||
"accum": 10000
|
||||
}],
|
||||
"proposer": {
|
||||
"ID": 3,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 10000,
|
||||
"pubKey": "0x046434e10a34ade13c4fea917346a9fd1473eac2138a0b4e2a36426871918be63188fde4edbf598457592c9a49fe3b0036dd5497079495d132e5045bf499c4bdb1",
|
||||
"signer": "0x1c4f0f054a0d6a1415382dc0fd83c6535188b220",
|
||||
"last_updated": 0,
|
||||
"accum": -40000
|
||||
}
|
||||
"accum": 5000
|
||||
}]
|
||||
},
|
||||
"selected_producers": [{
|
||||
"ID": 5,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 1,
|
||||
"power": 30,
|
||||
"pubKey": "0x04a36f6ed1f93acb0a38f4cacbe2467c72458ac41ce3b12b34d758205b2bc5d930a4e059462da7a0976c32fce766e1f7e8d73933ae72ac2af231fe161187743932",
|
||||
"signer": "0x836fe3e3dd0a5f77d9d5b0f67e48048aaafcd5a0",
|
||||
"signer": "0x9fB29AAc15b9A4B7F17c3385939b007540f4d791",
|
||||
"last_updated": 0,
|
||||
"accum": 10000
|
||||
}, {
|
||||
"ID": 1,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 1,
|
||||
"power": 20,
|
||||
"pubKey": "0x04a312814042a6655c8e5ecf0c52cba0b6a6f3291c87cc42260a3c0222410c0d0d59b9139d1c56542e5df0ce2fce3a86ce13e93bd9bde0dc8ff664f8dd5294dead",
|
||||
"signer": "0x925a91f8003aaeabea6037103123b93c50b86ca3",
|
||||
"signer": "0x96C42C56fdb78294F96B0cFa33c92bed7D75F96a",
|
||||
"last_updated": 0,
|
||||
"accum": 10000
|
||||
}, {
|
||||
"ID": 2,
|
||||
"startEpoch": 0,
|
||||
"endEpoch": 0,
|
||||
"power": 2,
|
||||
"power": 10,
|
||||
"pubKey": "0x0469536ae98030a7e83ec5ef3baffed2d05a32e31d978e58486f6bdb0fbbf240293838325116090190c0639db03f9cbd8b9aecfd269d016f46e3a2287fbf9ad232",
|
||||
"signer": "0xc787af4624cb3e80ee23ae7faac0f2acea2be34c",
|
||||
"last_updated": 0,
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ type MismatchingValidatorsError struct {
|
|||
|
||||
func (e *MismatchingValidatorsError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"Mismatching validators at block %d\nValidatorBytes from snapshot: %x\nValidatorBytes in Header: %x\n",
|
||||
"Mismatching validators at block %d\nValidatorBytes from snapshot: 0x%x\nValidatorBytes in Header: 0x%x\n",
|
||||
e.Number,
|
||||
e.ValidatorSetSnap,
|
||||
e.ValidatorSetHeader,
|
||||
|
|
@ -109,3 +109,36 @@ func (e *BlockTooSoonError) Error() string {
|
|||
e.Succession,
|
||||
)
|
||||
}
|
||||
|
||||
// UnauthorizedSignerError is returned if a header is signed by a non-authorized entity.
|
||||
type UnauthorizedSignerError struct {
|
||||
Number uint64
|
||||
Signer []byte
|
||||
}
|
||||
|
||||
func (e *UnauthorizedSignerError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"Validator set for block %d doesn't contain the signer 0x%x\n",
|
||||
e.Number,
|
||||
e.Signer,
|
||||
)
|
||||
}
|
||||
|
||||
// WrongDifficultyError is returned if the difficulty of a block doesn't match the
|
||||
// turn of the signer.
|
||||
type WrongDifficultyError struct {
|
||||
Number uint64
|
||||
Expected uint64
|
||||
Actual uint64
|
||||
Signer []byte
|
||||
}
|
||||
|
||||
func (e *WrongDifficultyError) Error() string {
|
||||
return fmt.Sprintf(
|
||||
"Wrong difficulty at block %d, expected: %d, actual %d. Signer was %x\n",
|
||||
e.Number,
|
||||
e.Expected,
|
||||
e.Actual,
|
||||
e.Signer,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
|
||||
// check if signer is in validator set
|
||||
if !snap.ValidatorSet.HasAddress(signer.Bytes()) {
|
||||
return nil, errUnauthorizedSigner
|
||||
return nil, &UnauthorizedSignerError{number, signer.Bytes()}
|
||||
}
|
||||
|
||||
if _, err = snap.GetSignerSuccessionNumber(signer); err != nil {
|
||||
|
|
@ -222,8 +222,8 @@ func (s *Snapshot) signers() []common.Address {
|
|||
return sigs
|
||||
}
|
||||
|
||||
// inturn returns if a signer at a given block height is in-turn or not.
|
||||
func (s *Snapshot) inturn(number uint64, signer common.Address, epoch uint64) uint64 {
|
||||
// Difficulty returns the difficulty for a particular signer at the current snapshot number
|
||||
func (s *Snapshot) Difficulty(signer common.Address) uint64 {
|
||||
// if signer is empty
|
||||
if bytes.Compare(signer.Bytes(), common.Address{}.Bytes()) == 0 {
|
||||
return 1
|
||||
|
|
|
|||
Loading…
Reference in a new issue