Skip to content

Commit

Permalink
Merge branch 'feature/qlight-develop-rebase' of https://github.com/ni…
Browse files Browse the repository at this point in the history
…colae-leonte-go/quorum into feature/qlight-develop-rebase
  • Loading branch information
nicolae-leonte-go committed Apr 6, 2022
2 parents a6f15db + 25b2f55 commit 912dae3
Show file tree
Hide file tree
Showing 17 changed files with 311 additions and 39 deletions.
6 changes: 6 additions & 0 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ func initGenesis(ctx *cli.Context) error {
if err != nil {
utils.Fatalf("maxCodeSize data invalid: %v", err)
}
if genesis.Config.IsQuorum {
err = genesis.Config.CheckTransitionsData()
if err != nil {
utils.Fatalf("transitions data invalid: %v", err)
}
}
// End Quorum

// Open and initialise both full and light databases
Expand Down
14 changes: 8 additions & 6 deletions cmd/geth/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,9 +392,10 @@ func TestFlagsConfig(t *testing.T) {
// QUORUM
// [Eth.Istanbul]
quorumIstanbul := eth.Istanbul
assert.Equal(t, uint64(10000), quorumIstanbul.RequestTimeout)
assert.Equal(t, uint64(1), quorumIstanbul.BlockPeriod)
assert.Equal(t, uint64(30000), quorumIstanbul.Epoch)
config := quorumIstanbul.GetConfig(nil)
assert.Equal(t, uint64(10000), config.RequestTimeout)
assert.Equal(t, uint64(1), config.BlockPeriod)
assert.Equal(t, uint64(30000), config.Epoch)
assert.Equal(t, big.NewInt(0), quorumIstanbul.Ceil2Nby3Block)
assert.Equal(t, istanbul.RoundRobin, quorumIstanbul.ProposerPolicy.Id) // conflict with genesis?
// END QUORUM
Expand Down Expand Up @@ -685,9 +686,10 @@ func testConfig(t *testing.T, cfg *gethConfig) {
// QUORUM
// [Eth.Quorum.Istanbul]
istanbul := cfg.Eth.Istanbul
assert.Equal(t, uint64(10000), istanbul.RequestTimeout)
assert.Equal(t, uint64(5), istanbul.BlockPeriod)
assert.Equal(t, uint64(30000), istanbul.Epoch)
config := istanbul.GetConfig(nil)
assert.Equal(t, uint64(10000), config.RequestTimeout)
assert.Equal(t, uint64(5), config.BlockPeriod)
assert.Equal(t, uint64(30000), config.Epoch)
assert.Equal(t, big.NewInt(0), istanbul.Ceil2Nby3Block)
// END QUORUM
}
9 changes: 9 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2461,14 +2461,23 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readOnly bool, useExist bool)
istanbulConfig.ProposerPolicy = istanbul.NewProposerPolicy(istanbul.ProposerPolicyId(config.Istanbul.ProposerPolicy))
istanbulConfig.Ceil2Nby3Block = config.Istanbul.Ceil2Nby3Block
istanbulConfig.TestQBFTBlock = config.Istanbul.TestQBFTBlock
if config.Transitions != nil && len(config.Transitions) != 0 {
istanbulConfig.Transitions = config.Transitions
}
engine = istanbulBackend.New(istanbulConfig, stack.GetNodeKey(), chainDb)
} else if config.IBFT != nil {
ibftConfig := setBFTConfig(config.IBFT.BFTConfig)
ibftConfig.TestQBFTBlock = nil
if config.Transitions != nil && len(config.Transitions) != 0 {
ibftConfig.Transitions = config.Transitions
}
engine = istanbulBackend.New(ibftConfig, stack.GetNodeKey(), chainDb)
} else if config.QBFT != nil {
qbftConfig := setBFTConfig(config.QBFT.BFTConfig)
qbftConfig.TestQBFTBlock = big.NewInt(0)
if config.Transitions != nil && len(config.Transitions) != 0 {
qbftConfig.Transitions = config.Transitions
}
engine = istanbulBackend.New(qbftConfig, stack.GetNodeKey(), chainDb)
} else if config.IsQuorum {
// for Raft
Expand Down
5 changes: 3 additions & 2 deletions cmd/utils/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ func TestQuorumConfigFlags(t *testing.T) {
assert.Equal(t, 12*time.Second, arbitraryEthConfig.EVMCallTimeOut, "EVMCallTimeOut value is incorrect")
assert.Equal(t, true, arbitraryEthConfig.QuorumChainConfig.MultiTenantEnabled(), "MultitenancyFlag value is incorrect")
assert.Equal(t, true, arbitraryEthConfig.QuorumChainConfig.PrivacyMarkerEnabled(), "QuorumEnablePrivacyMarker value is incorrect")
assert.Equal(t, uint64(23), arbitraryEthConfig.Istanbul.RequestTimeout, "IstanbulRequestTimeoutFlag value is incorrect")
assert.Equal(t, uint64(34), arbitraryEthConfig.Istanbul.BlockPeriod, "IstanbulBlockPeriodFlag value is incorrect")
config := arbitraryEthConfig.Istanbul.GetConfig(nil)
assert.Equal(t, uint64(23), config.RequestTimeout, "IstanbulRequestTimeoutFlag value is incorrect")
assert.Equal(t, uint64(34), config.BlockPeriod, "IstanbulBlockPeriodFlag value is incorrect")
assert.Equal(t, true, arbitraryEthConfig.RaftMode, "RaftModeFlag value is incorrect")
}
4 changes: 2 additions & 2 deletions consensus/istanbul/backend/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ func (sb *Backend) snapshot(chain consensus.ChainHeaderReader, number uint64, ha
}
// If an on-disk checkpoint snapshot can be found, use that
if number%checkpointInterval == 0 {
if s, err := loadSnapshot(sb.config.Epoch, sb.db, hash); err == nil {
if s, err := loadSnapshot(sb.config.GetConfig(new(big.Int).SetUint64(number)).Epoch, sb.db, hash); err == nil {
snap = s
sb.snapLogger(snap).Trace("BFT: loaded voting snapshot from database")
break
Expand All @@ -367,7 +367,7 @@ func (sb *Backend) snapshot(chain consensus.ChainHeaderReader, number uint64, ha
return nil, err
}

snap = newSnapshot(sb.config.Epoch, 0, genesis.Hash(), validator.NewSet(validators, sb.config.ProposerPolicy))
snap = newSnapshot(sb.config.GetConfig(new(big.Int).SetUint64(number)).Epoch, 0, genesis.Hash(), validator.NewSet(validators, sb.config.ProposerPolicy))
if err := sb.storeSnap(snap); err != nil {
return nil, err
}
Expand Down
7 changes: 4 additions & 3 deletions consensus/istanbul/backend/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,13 @@ func copyConfig(config *istanbul.Config) *istanbul.Config {
}

func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header {
blockNumber := parent.Number().Add(parent.Number(), common.Big1)
header := &types.Header{
ParentHash: parent.Hash(),
Number: parent.Number().Add(parent.Number(), common.Big1),
Number: blockNumber,
GasLimit: core.CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
GasUsed: 0,
Time: parent.Time() + config.BlockPeriod,
Time: parent.Time() + config.GetConfig(blockNumber).BlockPeriod,
Difficulty: istanbulcommon.DefaultDifficulty,
}
return header
Expand Down Expand Up @@ -310,7 +311,7 @@ func TestVerifyHeader(t *testing.T) {
// invalid timestamp
block = makeBlockWithoutSeal(chain, engine, chain.Genesis())
header = block.Header()
header.Time = chain.Genesis().Time() + (engine.config.BlockPeriod - 1)
header.Time = chain.Genesis().Time() + (engine.config.GetConfig(block.Number()).BlockPeriod - 1)
err = engine.VerifyHeader(chain, header, false)
if err != istanbulcommon.ErrInvalidTimestamp {
t.Errorf("error mismatch: have %v, want %v", err, istanbulcommon.ErrInvalidTimestamp)
Expand Down
5 changes: 3 additions & 2 deletions consensus/istanbul/backend/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,10 @@ func TestVoting(t *testing.T) {
// Assemble a chain of headers from the cast votes
headers := make([]*types.Header, len(tt.votes))
for j, vote := range tt.votes {
blockNumber := big.NewInt(int64(j) + 1)
headers[j] = &types.Header{
Number: big.NewInt(int64(j) + 1),
Time: uint64(int64(j) * int64(config.BlockPeriod)),
Number: blockNumber,
Time: uint64(int64(j) * int64(config.GetConfig(blockNumber).BlockPeriod)),
Coinbase: accounts.address(vote.validator),
Difficulty: istanbulcommon.DefaultDifficulty,
MixDigest: types.IstanbulDigest,
Expand Down
38 changes: 29 additions & 9 deletions consensus/istanbul/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"math/big"
"sync"

"github.com/ethereum/go-ethereum/params"
"github.com/naoina/toml"
)

Expand Down Expand Up @@ -125,6 +126,7 @@ type Config struct {
Ceil2Nby3Block *big.Int `toml:",omitempty"` // Number of confirmations required to move from one state to next [2F + 1 to Ceil(2N/3)]
AllowedFutureBlockTime uint64 `toml:",omitempty"` // Max time (in seconds) from current time allowed for blocks, before they're considered future blocks
TestQBFTBlock *big.Int `toml:",omitempty"` // Fork block at which block confirmations are done using qbft consensus instead of ibft
Transitions []params.Transition
}

var DefaultConfig = &Config{
Expand All @@ -147,17 +149,35 @@ func (c Config) QBFTBlockNumber() int64 {

// IsQBFTConsensusAt checks if qbft consensus is enabled for the block height identified by the given header
func (c *Config) IsQBFTConsensusAt(blockNumber *big.Int) bool {
// If qbftBlock is not defined in genesis qbft consensus is not used
if c.TestQBFTBlock == nil {
return false
if c.TestQBFTBlock != nil {
if c.TestQBFTBlock.Uint64() == 0 {
return true
}

if blockNumber.Cmp(c.TestQBFTBlock) >= 0 {
return true
}
}

if c.TestQBFTBlock.Uint64() == 0 {
return true
for i := 0; c.Transitions != nil && i < len(c.Transitions) && c.Transitions[i].Block.Cmp(blockNumber) <= 0; i++ {
if c.Transitions[i].Algorithm == params.QBFT {
return true
}
}
return false
}

if blockNumber.Cmp(c.TestQBFTBlock) >= 0 {
return true
func (c Config) GetConfig(blockNumber *big.Int) Config {
newConfig := c
for i := 0; c.Transitions != nil && i < len(c.Transitions) && c.Transitions[i].Block.Cmp(blockNumber) <= 0; i++ {
if c.Transitions[i].RequestTimeoutSeconds != 0 {
newConfig.RequestTimeout = c.Transitions[i].RequestTimeoutSeconds
}
if c.Transitions[i].EpochLength != 0 {
newConfig.Epoch = c.Transitions[i].EpochLength
}
if c.Transitions[i].BlockPeriodSeconds != 0 {
newConfig.BlockPeriod = c.Transitions[i].BlockPeriodSeconds
}
}
return false
return newConfig
}
84 changes: 84 additions & 0 deletions consensus/istanbul/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@
package istanbul

import (
"math/big"
"reflect"
"testing"

"github.com/ethereum/go-ethereum/params"
"github.com/naoina/toml"
"github.com/stretchr/testify/assert"
)
Expand All @@ -42,3 +45,84 @@ func TestProposerPolicy_MarshalTOML(t *testing.T) {
}
assert.Equal(t, output, b, "ProposerPolicy MarshalTOML mismatch")
}

func TestGetConfig(t *testing.T) {
if !reflect.DeepEqual(DefaultConfig.GetConfig(nil), *DefaultConfig) {
t.Errorf("error default config:\nexpected: %v\n", DefaultConfig)
}

config := DefaultConfig
config.Transitions = []params.Transition{{
Block: big.NewInt(1),
EpochLength: 40000,
}, {
Block: big.NewInt(3),
BlockPeriodSeconds: 5,
}, {
Block: big.NewInt(5),
RequestTimeoutSeconds: 15000,
}}
config1 := *DefaultConfig
config1.Epoch = 40000
config3 := config1
config3.BlockPeriod = 5
config5 := config3
config5.RequestTimeout = 15000

type test struct {
blockNumber int64
expectedConfig Config
}
tests := []test{
{1, config1},
{2, config1},
{3, config3},
{4, config3},
{5, config5},
{10, config5},
{100, config5},
}

for _, test := range tests {
c := config.GetConfig(big.NewInt(test.blockNumber))
if !reflect.DeepEqual(c, test.expectedConfig) {
t.Errorf("error mismatch:\nexpected: %v\ngot: %v\n", test.expectedConfig, c)
}
}
}

func TestIsQBFTConsensusAt(t *testing.T) {
config1 := *DefaultConfig
config1.TestQBFTBlock = nil
config2 := *DefaultConfig
config2.TestQBFTBlock = big.NewInt(5)
config3 := *DefaultConfig
config3.TestQBFTBlock = nil
config3.Transitions = []params.Transition{
{Block: big.NewInt(10), Algorithm: params.QBFT},
}
type test struct {
config Config
blockNumber int64
isQBFT bool
}
tests := []test{
{*DefaultConfig, 0, true},
{*DefaultConfig, 10, true},
{config1, 0, false},
{config1, 10, false},
{config2, 4, false},
{config2, 5, true},
{config2, 7, true},
{config3, 0, false},
{config3, 7, false},
{config3, 10, true},
{config3, 11, true},
}
for _, test := range tests {
isQbft := test.config.IsQBFTConsensusAt(big.NewInt(test.blockNumber))
if !reflect.DeepEqual(isQbft, test.isQBFT) {
t.Errorf("error mismatch:\nexpected: %v\ngot: %v\n", test.isQBFT, isQbft)
}
}
}
2 changes: 1 addition & 1 deletion consensus/istanbul/ibft/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ func (c *core) newRoundChangeTimer() {
c.stopTimer()

// set timeout based on the round number
timeout := time.Duration(c.config.RequestTimeout) * time.Millisecond
timeout := time.Duration(c.config.GetConfig(c.current.Sequence()).RequestTimeout) * time.Millisecond
round := c.current.Round().Uint64()
if round > 0 {
timeout += time.Duration(math.Pow(2, float64(round))) * time.Second
Expand Down
4 changes: 2 additions & 2 deletions consensus/istanbul/ibft/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func (e *Engine) verifyCascadingFields(chain consensus.ChainHeaderReader, header
}

// Ensure that the block's timestamp isn't too close to it's parent
if parent.Time+e.cfg.BlockPeriod > header.Time {
if parent.Time+e.cfg.GetConfig(parent.Number).BlockPeriod > header.Time {
return istanbulcommon.ErrInvalidTimestamp
}

Expand Down Expand Up @@ -284,7 +284,7 @@ func (e *Engine) Prepare(chain consensus.ChainHeaderReader, header *types.Header
header.Extra = extra

// set header's timestamp
header.Time = parent.Time + e.cfg.BlockPeriod
header.Time = parent.Time + e.cfg.GetConfig(header.Number).BlockPeriod
if header.Time < uint64(time.Now().Unix()) {
header.Time = uint64(time.Now().Unix())
}
Expand Down
2 changes: 1 addition & 1 deletion consensus/istanbul/qbft/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ func (c *core) newRoundChangeTimer() {
c.stopTimer()

// set timeout based on the round number
baseTimeout := time.Duration(c.config.RequestTimeout) * time.Millisecond
baseTimeout := time.Duration(c.config.GetConfig(c.current.Sequence()).RequestTimeout) * time.Millisecond
round := c.current.Round().Uint64()

timeout := baseTimeout * time.Duration(math.Pow(2, float64(round)))
Expand Down
4 changes: 2 additions & 2 deletions consensus/istanbul/qbft/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func (e *Engine) verifyCascadingFields(chain consensus.ChainHeaderReader, header
}

// Ensure that the block's timestamp isn't too close to it's parent
if parent.Time+e.cfg.BlockPeriod > header.Time {
if parent.Time+e.cfg.GetConfig(parent.Number).BlockPeriod > header.Time {
return istanbulcommon.ErrInvalidTimestamp
}

Expand Down Expand Up @@ -316,7 +316,7 @@ func (e *Engine) Prepare(chain consensus.ChainHeaderReader, header *types.Header
header.Difficulty = istanbulcommon.DefaultDifficulty

// set header's timestamp
header.Time = parent.Time + e.cfg.BlockPeriod
header.Time = parent.Time + e.cfg.GetConfig(header.Number).BlockPeriod
if header.Time < uint64(time.Now().Unix()) {
header.Time = uint64(time.Now().Unix())
}
Expand Down
3 changes: 3 additions & 0 deletions eth/ethconfig/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ func CreateConsensusEngine(stack *node.Node, chainConfig *params.ChainConfig, co
chainConfig.Clique.AllowedFutureBlockTime = config.Miner.AllowedFutureBlockTime //Quorum
return clique.New(chainConfig.Clique, db)
}
if chainConfig.Transitions != nil && len(chainConfig.Transitions) != 0 {
config.Istanbul.Transitions = chainConfig.Transitions
}
// If Istanbul is requested, set it up
if chainConfig.Istanbul != nil {
log.Warn("WARNING: The attribute config.istanbul is deprecated and will be removed in the future, please use config.ibft on genesis file")
Expand Down
Loading

0 comments on commit 912dae3

Please sign in to comment.