fix: Check block delay in verifyHeaders / remove empty chainId check (MAT-1080, MAT-1089) (#49)

* fix: Check block delay in verifyHeaders

* Pull block time check out of if condition

* fix: Always check chainId equality in heimdall response
This commit is contained in:
Arpit Agarwal 2020-04-20 11:53:05 +05:30 committed by GitHub
parent 710fb49226
commit d8c07f302a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 12 deletions

View file

@ -205,13 +205,13 @@ func CalcDifficulty(snap *Snapshot, signer common.Address, epoch uint64) *big.In
return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, epoch))
}
// CalcProducerDelay is the producer delay algorithm based on block time.
func CalcProducerDelay(snap *Snapshot, signer common.Address, period uint64, epoch uint64, producerDelay uint64) uint64 {
// if block is epoch start block, proposer will be inturn signer
if (snap.Number+1)%epoch == 0 {
// CalcProducerDelay is the block delay algorithm based on block time and period / producerDelay values in genesis
func CalcProducerDelay(number uint64, period uint64, sprint uint64, producerDelay uint64) uint64 {
// 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
if number%sprint == 0 {
return producerDelay
}
return period
}
@ -331,6 +331,17 @@ func (c *Bor) verifyHeader(chain consensus.ChainReader, header *types.Header, pa
}
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
if header.Time > uint64(time.Now().Unix()) {
return consensus.ErrFutureBlock
@ -654,7 +665,7 @@ func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error {
return consensus.ErrUnknownAncestor
}
header.Time = parent.Time + CalcProducerDelay(snap, c.signer, c.config.Period, c.config.Sprint, c.config.ProducerDelay)
header.Time = parent.Time + CalcProducerDelay(number, c.config.Period, c.config.Sprint, c.config.ProducerDelay)
if header.Time < uint64(time.Now().Unix()) {
header.Time = uint64(time.Now().Unix())
}
@ -1190,7 +1201,7 @@ func (c *Bor) CommitStates(
}
// check if chain id matches with event record
if eventRecord.ChainID != "" && eventRecord.ChainID != c.chainConfig.ChainID.String() {
if eventRecord.ChainID != c.chainConfig.ChainID.String() {
return fmt.Errorf(
"Chain id proposed state in span, %s, and bor chain id, %s, doesn't match",
eventRecord.ChainID,

View file

@ -32,7 +32,7 @@ func TestCommitSpan(t *testing.T) {
db := init.ethereum.ChainDb()
block := init.genesis.ToBlock(db)
// Build 1st block's header
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor.Period)
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
statedb, err := chain.State()
if err != nil {
@ -89,7 +89,7 @@ func TestIsValidatorAction(t *testing.T) {
db := init.ethereum.ChainDb()
block := init.genesis.ToBlock(db)
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor.Period)
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
statedb, err := chain.State()
if err != nil {
t.Fatalf("%s", err)
@ -101,7 +101,7 @@ func TestIsValidatorAction(t *testing.T) {
var headers []*types.Header
for i := int64(2); i <= 255; i++ {
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor.Period)
header := buildMinimalNextHeader(t, block, init.genesis.Config.Bor)
headers = append(headers, header)
block = types.NewBlockWithHeader(header)
}

View file

@ -16,6 +16,7 @@ import (
"github.com/maticnetwork/bor/eth"
"github.com/maticnetwork/bor/ethdb"
"github.com/maticnetwork/bor/node"
"github.com/maticnetwork/bor/params"
)
var (
@ -99,11 +100,11 @@ func insertNewBlock(t *testing.T, _bor *bor.Bor, chain *core.BlockChain, header
}
}
func buildMinimalNextHeader(t *testing.T, block *types.Block, period uint64) *types.Header {
func buildMinimalNextHeader(t *testing.T, block *types.Block, borConfig *params.BorConfig) *types.Header {
header := block.Header()
header.Number.Add(header.Number, big.NewInt(1))
header.ParentHash = block.Hash()
header.Time += (period + 1)
header.Time += bor.CalcProducerDelay(header.Number.Uint64(), borConfig.Period, borConfig.Sprint, borConfig.ProducerDelay)
header.Extra = make([]byte, 97) // vanity (32) + extraSeal (65)
_key, _ := hex.DecodeString(privKey)
sig, err := secp256k1.Sign(crypto.Keccak256(bor.BorRLP(header)), _key)

View file

@ -31,6 +31,9 @@ var (
// to the current node.
ErrFutureBlock = errors.New("block in the future")
// ErrBlockTooSoon is returned when the period / producerDelay values in the genesis were not respected
ErrBlockTooSoon = errors.New("block was produced sooner than expected")
// ErrInvalidNumber is returned if a block's number doesn't equal it's parent's
// plus one.
ErrInvalidNumber = errors.New("invalid block number")