good morning!!!!

Skip to content
Snippets Groups Projects
Commit c27b8b78 authored by atvanguard's avatar atvanguard Committed by Arpit Agarwal
Browse files

new: Add wiggle to block time

parent 4f850ede
No related branches found
No related tags found
No related merge requests found
...@@ -111,6 +111,7 @@ func (w *wizard) makeGenesis() { ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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 @@ ...@@ -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. ...@@ -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 { ...@@ -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 { ...@@ -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
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment