Skip to content

Commit

Permalink
Xin-124 Deal with Block Time mine time (ethereum#55)
Browse files Browse the repository at this point in the history
* add wait v2 period in miner

* add perido initial

* add mine and wait time

* update todo

* merge all xdc test config into 1
  • Loading branch information
Liam authored Feb 13, 2022
1 parent 4424c7d commit 5a3acd1
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 130 deletions.
25 changes: 19 additions & 6 deletions consensus/XDPoS/XDPoS.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ type XDPoS struct {
// Transaction cache, only make sense for adaptor level
signingTxsCache *lru.Cache

// Share Channel
WaitPeriodCh chan int // Miner wait Period Channel

// Trading and lending service
GetXDCXService func() utils.TradingService
GetLendingService func() utils.LendingService
Expand All @@ -71,6 +74,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
config.Epoch = utils.EpochLength
}

waitPeriodCh := make(chan int)
// TODO: This shall be configurable or replaced
config.V2 = params.DevnetXDPoSV2Config

Expand All @@ -81,9 +85,11 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS {
config: config,
db: db,

WaitPeriodCh: waitPeriodCh,

signingTxsCache: signingTxsCache,
EngineV1: engine_v1.New(config, db),
EngineV2: engine_v2.New(config, db),
EngineV2: engine_v2.New(config, db, waitPeriodCh),
}
}

Expand All @@ -97,18 +103,23 @@ func NewFaker(db ethdb.Database, chainConfig *params.ChainConfig) *XDPoS {
conf = chainConfig.XDPoS
}

waitPeriodCh := make(chan int)

// Allocate the snapshot caches and create the engine
signingTxsCache, _ := lru.New(utils.BlockSignersCacheLimit)

fakeEngine = &XDPoS{
config: conf,
db: db,
config: conf,
db: db,

WaitPeriodCh: waitPeriodCh,

GetXDCXService: func() utils.TradingService { return nil },
GetLendingService: func() utils.LendingService { return nil },

signingTxsCache: signingTxsCache,
EngineV1: engine_v1.NewFaker(db, conf),
EngineV2: engine_v2.New(conf, db),
EngineV2: engine_v2.New(conf, db, waitPeriodCh),
}
return fakeEngine
}
Expand Down Expand Up @@ -305,8 +316,10 @@ func (x *XDPoS) GetMasternodesByNumber(chain consensus.ChainReader, blockNumber
func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (bool, error) {
if x.config.V2.SwitchBlock != nil && parent.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
err := x.initialV2(chain, parent)
log.Error("[YourTurn] Error when initialise v2", "Error", err, "ParentBlock", parent)
return false, err
if err != nil {
log.Error("[YourTurn] Error when initialise v2", "Error", err, "ParentBlock", parent)
return false, err
}
}
switch x.config.BlockConsensusVersion(big.NewInt(parent.Number.Int64() + 1)) {
case params.ConsensusEngineVersion2:
Expand Down
28 changes: 24 additions & 4 deletions consensus/XDPoS/engines/engine_v2/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ type XDPoS_v2 struct {
lock sync.RWMutex // Protects the signer fields
signLock sync.RWMutex // Protects the signer fields

BroadcastCh chan interface{}
BroadcastCh chan interface{}
waitPeriodCh chan int

timeoutWorker *countdown.CountdownTimer // Timer to generate broadcast timeout msg if threashold reached

timeoutPool *utils.Pool
Expand All @@ -54,7 +56,7 @@ type XDPoS_v2 struct {
HookReward func(chain consensus.ChainReader, state *state.StateDB, parentState *state.StateDB, header *types.Header) (error, map[string]interface{})
}

func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v2 {
func New(config *params.XDPoSConfig, db ethdb.Database, waitPeriodCh chan int) *XDPoS_v2 {
// Setup Timer
duration := time.Duration(config.V2.TimeoutWorkerDuration) * time.Second
timer := countdown.NewCountDown(duration)
Expand All @@ -74,8 +76,10 @@ func New(config *params.XDPoSConfig, db ethdb.Database) *XDPoS_v2 {
epochSwitches: epochSwitches,
timeoutWorker: timer,
BroadcastCh: make(chan interface{}),
timeoutPool: timeoutPool,
votePool: votePool,
waitPeriodCh: waitPeriodCh,

timeoutPool: timeoutPool,
votePool: votePool,

highestTimeoutCert: &utils.TimeoutCert{
Round: utils.Round(0),
Expand Down Expand Up @@ -144,6 +148,16 @@ func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header, ma
snap := newSnapshot(lastGapNum, lastGapHeader.Hash(), x.currentRound, x.highestQuorumCert, masternodes)
x.snapshots.Add(snap.Hash, snap)
storeSnapshot(snap, x.db)

// Initial timeout
log.Info("[Initial] miner wait period", "period", x.config.WaitPeriod)

// avoid deadlock
go func() {
x.waitPeriodCh <- x.config.V2.WaitPeriod
}()

log.Info("[Initial] finish initialisation")
return nil
}

Expand Down Expand Up @@ -332,6 +346,12 @@ func (x *XDPoS_v2) YourTurn(chain consensus.ChainReader, parent *types.Header, s
x.lock.RLock()
defer x.lock.RUnlock()

waitedTime := time.Now().Unix() - parent.Time.Int64()
if waitedTime < int64(x.config.V2.MinePeriod) {
log.Trace("[YourTurn] wait after mine period", "minePeriod", x.config.V2.MinePeriod, "waitedTime", waitedTime)
return false, nil
}

round := x.currentRound
isEpochSwitch, _, err := x.IsEpochSwitchAtRound(round, parent)
if err != nil {
Expand Down
56 changes: 28 additions & 28 deletions consensus/tests/adaptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
)

func TestAdaptorShouldGetAuthorForDifferentConsensusVersion(t *testing.T) {
blockchain, backend, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 10, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, backend, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 900, params.TestXDPoSMockChainConfig, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)

addressFromAdaptor, errorAdaptor := adaptor.Author(currentBlock.Header())
Expand All @@ -30,31 +30,31 @@ func TestAdaptorShouldGetAuthorForDifferentConsensusVersion(t *testing.T) {
assert.Equal(t, addressFromAdaptor, addressFromV1Engine)

// Insert one more block to make it above 10, which means now we are on v2 of consensus engine
// Insert block 11
// Insert block 901

blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", 11)
blockCoinBase := fmt.Sprintf("0x111000000000000000000000000000000%03d", 901)
merkleRoot := "35999dded35e8db12de7e6c1471eb9670c162eec616ecebbaf4fddd4676fb930"
header := &types.Header{
Root: common.HexToHash(merkleRoot),
Number: big.NewInt(int64(11)),
Number: big.NewInt(int64(901)),
ParentHash: currentBlock.Hash(),
Coinbase: common.HexToAddress(blockCoinBase),
}
err := generateSignature(backend, adaptor, header)
if err != nil {
t.Fatal(err)
}
block11, err := createBlockFromHeader(blockchain, header, nil)
block901, err := createBlockFromHeader(blockchain, header, nil)
if err != nil {
t.Fatal(err)
}
blockchain.InsertBlock(block11)
blockchain.InsertBlock(block901)

addressFromAdaptor, errorAdaptor = adaptor.Author(block11.Header())
addressFromAdaptor, errorAdaptor = adaptor.Author(block901.Header())
if errorAdaptor != nil {
t.Fatalf("Failed while trying to get Author from adaptor")
}
addressFromV2Engine, errV2 := adaptor.EngineV2.Author(block11.Header())
addressFromV2Engine, errV2 := adaptor.EngineV2.Author(block901.Header())
if errV2 != nil {
t.Fatalf("Failed while trying to get Author from engine v2")
}
Expand All @@ -63,7 +63,7 @@ func TestAdaptorShouldGetAuthorForDifferentConsensusVersion(t *testing.T) {
}

func TestAdaptorGetMasternodesFromCheckpointHeader(t *testing.T) {
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 1, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 1, params.TestXDPoSMockChainConfig, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
headerV1 := currentBlock.Header()
headerV1.Extra = common.Hex2Bytes("d7830100018358444388676f312e31352e38856c696e757800000000000000000278c350152e15fa6ffc712a5a73d704ce73e2e103d9e17ae3ff2c6712e44e25b09ac5ee91f6c9ff065551f0dcac6f00cae11192d462db709be3758ccef312ee5eea8d7bad5374c6a652150515d744508b61c1a4deb4e4e7bf057e4e3824c11fd2569bcb77a52905cda63b5a58507910bed335e4c9d87ae0ecdfafd400")
Expand All @@ -75,7 +75,7 @@ func TestAdaptorGetMasternodesFromCheckpointHeader(t *testing.T) {
assert.True(t, reflect.DeepEqual(masternodesV1, masternodesV2), "GetMasternodesFromCheckpointHeader in adaptor for v1 v2 not equal", "v1", masternodesV1, "v2", masternodesV2)
}
func TestAdaptorIsEpochSwitch(t *testing.T) {
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 1, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 1, params.TestXDPoSMockChainConfig, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
header := currentBlock.Header()
// v1
Expand Down Expand Up @@ -174,20 +174,20 @@ func TestAdaptorIsEpochSwitch(t *testing.T) {

func TestAdaptorGetMasternodesV2(t *testing.T) {
// we skip test for v1 since it's hard to make a real genesis block
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 10, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 900, params.TestXDPoSMockChainConfig, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
blockNum := 11
blockNum := 901
blockCoinBase := "0x111000000000000000000000000000000123"
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)

// block 11 is the first v2 block, and is treated as epoch switch block
// block 901 is the first v2 block, and is treated as epoch switch block
blockchain.InsertBlock(currentBlock)
masternodes1 := adaptor.GetMasternodes(blockchain, currentBlock.Header())
assert.Equal(t, 4, len(masternodes1))
masternodes1ByNumber := adaptor.GetMasternodesByNumber(blockchain, currentBlock.NumberU64())
assert.True(t, reflect.DeepEqual(masternodes1, masternodes1ByNumber), "at block number", blockNum)
for blockNum = 12; blockNum < 15; blockNum++ {
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, int64(blockNum-10), blockCoinBase, signer, signFn)
for blockNum = 902; blockNum < 915; blockNum++ {
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, int64(blockNum-900), blockCoinBase, signer, signFn)
blockchain.InsertBlock(currentBlock)
masternodes2 := adaptor.GetMasternodes(blockchain, currentBlock.Header())
assert.True(t, reflect.DeepEqual(masternodes1, masternodes2), "at block number", blockNum)
Expand All @@ -197,32 +197,32 @@ func TestAdaptorGetMasternodesV2(t *testing.T) {
}

func TestGetCurrentEpochSwitchBlock(t *testing.T) {
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 10, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 900, params.TestXDPoSMockChainConfig, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)

// V1
currentCheckpointNumber, epochNum, err := adaptor.GetCurrentEpochSwitchBlock(blockchain, big.NewInt(9))
currentCheckpointNumber, epochNum, err := adaptor.GetCurrentEpochSwitchBlock(blockchain, big.NewInt(900))
assert.Nil(t, err)
assert.Equal(t, uint64(0), currentCheckpointNumber)
assert.Equal(t, uint64(0), epochNum)
assert.Equal(t, uint64(900), currentCheckpointNumber)
assert.Equal(t, uint64(1), epochNum)

// V2
blockNum := 11
blockNum := 901
blockCoinBase := "0x111000000000000000000000000000000123"
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
blockchain.InsertBlock(currentBlock)
currentCheckpointNumber, epochNum, err = adaptor.GetCurrentEpochSwitchBlock(blockchain, currentBlock.Number())
assert.Nil(t, err)
assert.Equal(t, uint64(11), currentCheckpointNumber)
assert.Equal(t, uint64(0), epochNum)
assert.Equal(t, uint64(901), currentCheckpointNumber)
assert.Equal(t, uint64(1), epochNum)

for blockNum = 12; blockNum < 15; blockNum++ {
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, int64(blockNum-10), blockCoinBase, signer, signFn)
for blockNum = 902; blockNum < 915; blockNum++ {
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, int64(blockNum-900), blockCoinBase, signer, signFn)

blockchain.InsertBlock(currentBlock)
currentCheckpointNumber, epochNum, err := adaptor.GetCurrentEpochSwitchBlock(blockchain, currentBlock.Number())
assert.Nil(t, err)
assert.Equal(t, uint64(11), currentCheckpointNumber)
assert.Equal(t, uint64(0), epochNum)
assert.Equal(t, uint64(901), currentCheckpointNumber)
assert.Equal(t, uint64(1), epochNum)
}
}
28 changes: 18 additions & 10 deletions consensus/tests/authorised_masternode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tests
import (
"math/big"
"testing"
"time"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
Expand Down Expand Up @@ -73,11 +74,11 @@ func TestIsAuthorisedMNForConsensusV1(t *testing.T) {

func TestIsAuthorisedMNForConsensusV2(t *testing.T) {
// we skip test for v1 since it's hard to make a real genesis block
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 10, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 900, params.TestXDPoSMockChainConfig, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
blockNum := 11
blockNum := 901
blockCoinBase := "0x111000000000000000000000000000000123"
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
blockchain.InsertBlock(currentBlock)

// As long as the address is in the master node list, they are all valid
Expand All @@ -93,17 +94,23 @@ func TestIsAuthorisedMNForConsensusV2(t *testing.T) {

func TestIsYourTurnConsensusV2(t *testing.T) {
// we skip test for v1 since it's hard to make a real genesis block
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 10, params.TestXDPoSMockChainConfigWithV2Engine, 0)

blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 900, params.TestXDPoSMockChainConfig, 0)
minePeriod := params.TestXDPoSV2Config.MinePeriod
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
blockNum := 11
blockNum := 901
blockCoinBase := "0x111000000000000000000000000000000123"
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, 1, blockCoinBase, signer, signFn)
blockchain.InsertBlock(currentBlock)

// The first address is valid
// Less then Mine Period
isYourTurn, err := adaptor.YourTurn(blockchain, currentBlock.Header(), common.HexToAddress("xdc703c4b2bD70c169f5717101CaeE543299Fc946C7"))
assert.Nil(t, err)
assert.False(t, isYourTurn)

time.Sleep(time.Duration(minePeriod) * time.Second)
// The first address is valid
isYourTurn, err = adaptor.YourTurn(blockchain, currentBlock.Header(), common.HexToAddress("xdc703c4b2bD70c169f5717101CaeE543299Fc946C7"))
assert.Nil(t, err)
assert.True(t, isYourTurn)

// The second and third address are not valid
Expand All @@ -115,9 +122,10 @@ func TestIsYourTurnConsensusV2(t *testing.T) {
assert.False(t, isYourTurn)

// We continue to grow the chain which will increase the round number
blockNum = 12
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfigWithV2Engine, currentBlock, blockNum, int64(blockNum-10), blockCoinBase, signer, signFn)
blockNum = 902
currentBlock = CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, blockNum, int64(blockNum-900), blockCoinBase, signer, signFn)
blockchain.InsertBlock(currentBlock)
time.Sleep(time.Duration(minePeriod) * time.Second)

adaptor.EngineV2.SetNewRoundFaker(1, false)
isYourTurn, _ = adaptor.YourTurn(blockchain, currentBlock.Header(), common.HexToAddress("xdc703c4b2bD70c169f5717101CaeE543299Fc946C7"))
Expand Down
2 changes: 1 addition & 1 deletion consensus/tests/block_signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ func TestVoteShouldNotBeAffectedByFork(t *testing.T) {
/*
// Pending for creating cross version blocks
func TestV2UpdateSignerListIfVotedBeforeGap(t *testing.T) {
config := params.TestXDPoSMockChainConfigWithV2EngineEpochSwitch
config := params.TestXDPoSMockChainConfig
blockchain, backend, parentBlock, _ := PrepareXDCTestBlockChain(t, int(config.XDPoS.Epoch)+GAP-2, config)
// Insert first Block 1349
t.Logf("Inserting block with propose at 1349...")
Expand Down
2 changes: 1 addition & 1 deletion consensus/tests/countdown_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func TestCountdownTimeoutToSendTimeoutMessage(t *testing.T) {
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfigWithV2Engine, 0)
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfig, 0)
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2

engineV2.SetNewRoundFaker(utils.Round(1), true)
Expand Down
8 changes: 5 additions & 3 deletions consensus/tests/mine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import (
)

func TestYourTurnInitialV2(t *testing.T) {
config := params.TestXDPoSMockChainConfigWithV2EngineEpochSwitch
config := params.TestXDPoSMockChainConfig
blockchain, _, parentBlock, _ := PrepareXDCTestBlockChain(t, int(config.XDPoS.Epoch)-1, config)
minePeriod := config.XDPoS.V2.MinePeriod
adaptor := blockchain.Engine().(*XDPoS.XDPoS)

// Insert block 900
Expand All @@ -36,6 +37,7 @@ func TestYourTurnInitialV2(t *testing.T) {
t.Fatal(err)
}
blockchain.InsertBlock(block900)
time.Sleep(time.Duration(minePeriod) * time.Second)

// YourTurn is called before mine first v2 block
b, err := adaptor.YourTurn(blockchain, block900.Header(), common.HexToAddress("xdc0278C350152e15fa6FFC712a5A73D704Ce73E2E1"))
Expand All @@ -57,7 +59,7 @@ func TestYourTurnInitialV2(t *testing.T) {
}

func TestUpdateMasterNodes(t *testing.T) {
config := params.TestXDPoSMockChainConfigWithV2EngineEpochSwitch
config := params.TestXDPoSMockChainConfig
blockchain, backend, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, int(config.XDPoS.Epoch+config.XDPoS.Gap)-1, config, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
x := adaptor.EngineV2
Expand Down Expand Up @@ -121,7 +123,7 @@ func TestUpdateMasterNodes(t *testing.T) {
}

func TestPrepare(t *testing.T) {
config := params.TestXDPoSMockChainConfigWithV2EngineEpochSwitch
config := params.TestXDPoSMockChainConfig
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, int(config.XDPoS.Epoch), config, 0)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)

Expand Down
Loading

0 comments on commit 5a3acd1

Please sign in to comment.