mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 01:13:45 +00:00
new: Add wiggle to block time
This commit is contained in:
parent
4f850edec2
commit
c27b8b7801
7 changed files with 51 additions and 27 deletions
|
|
@ -111,6 +111,7 @@ func (w *wizard) makeGenesis() {
|
||||||
Period: 1,
|
Period: 1,
|
||||||
ProducerDelay: 5,
|
ProducerDelay: 5,
|
||||||
Sprint: 60,
|
Sprint: 60,
|
||||||
|
BackupMultiplier: 1,
|
||||||
ValidatorContract: "0x0000000000000000000000000000000000001000",
|
ValidatorContract: "0x0000000000000000000000000000000000001000",
|
||||||
StateReceiverContract: "0x0000000000000000000000000000000000001001",
|
StateReceiverContract: "0x0000000000000000000000000000000000001001",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -207,14 +207,18 @@ func CalcDifficulty(snap *Snapshot, signer common.Address, sprint uint64) *big.I
|
||||||
return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, sprint))
|
return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, sprint))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalcProducerDelay is the block delay algorithm based on block time and period / producerDelay values in genesis
|
// CalcProducerDelay is the block delay algorithm based on block time, period, producerDelay and turn-ness of a signer
|
||||||
func CalcProducerDelay(number uint64, period uint64, sprint uint64, producerDelay uint64) uint64 {
|
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`.
|
// When the block is the first block of the sprint, it is expected to be delayed by `producerDelay`.
|
||||||
// That is to allow time for block propagation in the last sprint
|
// That is to allow time for block propagation in the last sprint
|
||||||
if number%sprint == 0 {
|
delay := c.Period
|
||||||
return producerDelay
|
if number%c.Sprint == 0 {
|
||||||
|
delay = c.ProducerDelay
|
||||||
}
|
}
|
||||||
return period
|
if succession > 0 {
|
||||||
|
delay += uint64(succession) * c.BackupMultiplier
|
||||||
|
}
|
||||||
|
return delay
|
||||||
}
|
}
|
||||||
|
|
||||||
// BorRLP returns the rlp bytes which needs to be signed for the bor
|
// BorRLP returns the rlp bytes which needs to be signed for the bor
|
||||||
|
|
@ -334,17 +338,6 @@ func (c *Bor) verifyHeader(chain consensus.ChainReader, header *types.Header, pa
|
||||||
}
|
}
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
|
|
||||||
var parent *types.Header
|
|
||||||
if len(parents) > 0 { // if parents is nil, len(parents) is zero
|
|
||||||
parent = parents[len(parents)-1]
|
|
||||||
} else if number > 0 {
|
|
||||||
parent = chain.GetHeader(header.ParentHash, number-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if parent != nil && header.Time < parent.Time+CalcProducerDelay(number, c.config.Period, c.config.Sprint, c.config.ProducerDelay) {
|
|
||||||
return consensus.ErrBlockTooSoon
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't waste time checking blocks from the future
|
// Don't waste time checking blocks from the future
|
||||||
if header.Time > uint64(time.Now().Unix()) {
|
if header.Time > uint64(time.Now().Unix()) {
|
||||||
return consensus.ErrFutureBlock
|
return consensus.ErrFutureBlock
|
||||||
|
|
@ -590,10 +583,22 @@ func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, pare
|
||||||
return errUnauthorizedSigner
|
return errUnauthorizedSigner
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err = snap.GetSignerSuccessionNumber(signer); err != nil {
|
succession, err := snap.GetSignerSuccessionNumber(signer)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parent *types.Header
|
||||||
|
if len(parents) > 0 { // if parents is nil, len(parents) is zero
|
||||||
|
parent = parents[len(parents)-1]
|
||||||
|
} else if number > 0 {
|
||||||
|
parent = chain.GetHeader(header.ParentHash, number-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if parent != nil && header.Time < parent.Time+CalcProducerDelay(number, succession, c.config) {
|
||||||
|
return &BlockTooSoonError{number, succession}
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that the difficulty corresponds to the turn-ness of the signer
|
// Ensure that the difficulty corresponds to the turn-ness of the signer
|
||||||
if !c.fakeDiff {
|
if !c.fakeDiff {
|
||||||
difficulty := snap.inturn(header.Number.Uint64(), signer, c.config.Sprint)
|
difficulty := snap.inturn(header.Number.Uint64(), signer, c.config.Sprint)
|
||||||
|
|
@ -654,7 +659,11 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
|
||||||
return consensus.ErrUnknownAncestor
|
return consensus.ErrUnknownAncestor
|
||||||
}
|
}
|
||||||
|
|
||||||
header.Time = parent.Time + CalcProducerDelay(number, c.config.Period, c.config.Sprint, c.config.ProducerDelay)
|
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()) {
|
if header.Time < uint64(time.Now().Unix()) {
|
||||||
header.Time = uint64(time.Now().Unix())
|
header.Time = uint64(time.Now().Unix())
|
||||||
}
|
}
|
||||||
|
|
@ -765,8 +774,8 @@ func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan
|
||||||
|
|
||||||
// Sweet, the protocol permits us to sign the block, wait for our time
|
// Sweet, the protocol permits us to sign the block, wait for our time
|
||||||
delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
|
delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
|
||||||
wiggle := time.Duration(2*c.config.Period) * time.Second * time.Duration(successionNumber)
|
// wiggle was already accounted for in header.Time, this is just for logging
|
||||||
delay += wiggle
|
wiggle := time.Duration(successionNumber) * time.Duration(c.config.BackupMultiplier) * time.Second
|
||||||
|
|
||||||
// Sign all the things!
|
// Sign all the things!
|
||||||
sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header))
|
sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header))
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,7 @@ func TestCommitSpan(t *testing.T) {
|
||||||
// Mock HeimdallClient.FetchWithRetry to return span data from span.json
|
// Mock HeimdallClient.FetchWithRetry to return span data from span.json
|
||||||
res, heimdallSpan := loadSpanFromFile(t)
|
res, heimdallSpan := loadSpanFromFile(t)
|
||||||
h := &mocks.IHeimdallClient{}
|
h := &mocks.IHeimdallClient{}
|
||||||
// FetchWithRetry is invoked 3 times
|
h.On("FetchWithRetry", "bor", "span", "1").Return(res, nil)
|
||||||
// 1. bor.FinalizeAndAssemble to prepare a new block when calling insertNewBlock
|
|
||||||
// 2. bor.Finalize via(bc.insertChain => bc.processor.Process)
|
|
||||||
// 3. bor.FinalizeAndAssemble via worker.commit
|
|
||||||
h.On("FetchWithRetry", "bor", "span", "1").Return(res, nil).Times(3)
|
|
||||||
_bor.SetHeimdallClient(h)
|
_bor.SetHeimdallClient(h)
|
||||||
|
|
||||||
db := init.ethereum.ChainDb()
|
db := init.ethereum.ChainDb()
|
||||||
|
|
@ -45,7 +41,10 @@ func TestCommitSpan(t *testing.T) {
|
||||||
block = insertNewBlock(t, _bor, chain, header, statedb, _key)
|
block = insertNewBlock(t, _bor, chain, header, statedb, _key)
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.True(t, h.AssertNumberOfCalls(t, "FetchWithRetry", 3))
|
// FetchWithRetry is invoked 2 times
|
||||||
|
// 1. bor.FinalizeAndAssemble to prepare a new block when calling insertNewBlock
|
||||||
|
// 2. bor.Finalize via(bc.insertChain => bc.processor.Process)
|
||||||
|
assert.True(t, h.AssertNumberOfCalls(t, "FetchWithRetry", 2))
|
||||||
validators, err := _bor.GetCurrentValidators(sprintSize, 256) // new span starts at 256
|
validators, err := _bor.GetCurrentValidators(sprintSize, 256) // new span starts at 256
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err)
|
t.Fatalf("%s", err)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
"bor": {
|
"bor": {
|
||||||
"period": 1,
|
"period": 1,
|
||||||
"producerDelay": 4,
|
"producerDelay": 4,
|
||||||
|
"backupMultiplier": 1,
|
||||||
"sprint": 4,
|
"sprint": 4,
|
||||||
"validatorContract": "0x0000000000000000000000000000000000001000",
|
"validatorContract": "0x0000000000000000000000000000000000001000",
|
||||||
"stateReceiverContract": "0x0000000000000000000000000000000000001001"
|
"stateReceiverContract": "0x0000000000000000000000000000000000001001"
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ func buildMinimalNextHeader(t *testing.T, block *types.Block, borConfig *params.
|
||||||
header := block.Header()
|
header := block.Header()
|
||||||
header.Number.Add(header.Number, big.NewInt(1))
|
header.Number.Add(header.Number, big.NewInt(1))
|
||||||
header.ParentHash = block.Hash()
|
header.ParentHash = block.Hash()
|
||||||
header.Time += bor.CalcProducerDelay(header.Number.Uint64(), borConfig.Period, borConfig.Sprint, borConfig.ProducerDelay)
|
header.Time += bor.CalcProducerDelay(header.Number.Uint64(), 0, borConfig)
|
||||||
header.Extra = make([]byte, 32+65) // vanity + extraSeal
|
header.Extra = make([]byte, 32+65) // vanity + extraSeal
|
||||||
|
|
||||||
currentValidators := []*bor.Validator{bor.NewValidator(addr, 10)}
|
currentValidators := []*bor.Validator{bor.NewValidator(addr, 10)}
|
||||||
|
|
|
||||||
|
|
@ -96,3 +96,16 @@ func (e *MismatchingValidatorsError) Error() string {
|
||||||
e.ValidatorSetHeader,
|
e.ValidatorSetHeader,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BlockTooSoonError struct {
|
||||||
|
Number uint64
|
||||||
|
Succession int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *BlockTooSoonError) Error() string {
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"Block %d was created too soon. Signer turn-ness number is %d\n",
|
||||||
|
e.Number,
|
||||||
|
e.Succession,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,7 @@ type BorConfig struct {
|
||||||
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
|
Period uint64 `json:"period"` // Number of seconds between blocks to enforce
|
||||||
ProducerDelay uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval
|
ProducerDelay uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval
|
||||||
Sprint uint64 `json:"sprint"` // Epoch length to proposer
|
Sprint uint64 `json:"sprint"` // Epoch length to proposer
|
||||||
|
BackupMultiplier uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time
|
||||||
ValidatorContract string `json:"validatorContract"` // Validator set contract
|
ValidatorContract string `json:"validatorContract"` // Validator set contract
|
||||||
StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract
|
StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue