From fe0f1a651e67d601b4beb5129ce548d7e5dd5e8c Mon Sep 17 00:00:00 2001 From: Paladz Date: Mon, 25 Nov 2019 11:33:53 +0800 Subject: [PATCH] timeout level (#450) * timeout level * fix ci * edit for code review * edit for code review --- proposal/blockproposer/blockproposer.go | 12 ++++--- proposal/proposal.go | 64 ++++++++++++++++++++------------- test/bench_blockchain_test.go | 2 +- test/performance/mining_test.go | 2 +- 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/proposal/blockproposer/blockproposer.go b/proposal/blockproposer/blockproposer.go index 7b7c0c46..3bf2243b 100644 --- a/proposal/blockproposer/blockproposer.go +++ b/proposal/blockproposer/blockproposer.go @@ -16,8 +16,11 @@ import ( ) const ( - logModule = "blockproposer" - timeProportionDenominator = 3 + logModule = "blockproposer" + warnTimeNum = 2 + warnTimeDenom = 5 + criticalTimeNum = 4 + criticalTimeDenom = 5 ) // BlockProposer propose several block in specified time range @@ -75,8 +78,9 @@ func (b *BlockProposer) generateBlocks() { continue } - timeoutDuration := time.Duration(consensus.ActiveNetParams.BlockTimeInterval/timeProportionDenominator) * time.Millisecond - block, err := proposal.NewBlockTemplate(b.chain, b.accountManager, nextBlockTime, timeoutDuration) + warnDuration := time.Duration(consensus.ActiveNetParams.BlockTimeInterval*warnTimeNum/warnTimeDenom) * time.Millisecond + criticalDuration := time.Duration(consensus.ActiveNetParams.BlockTimeInterval*criticalTimeNum/criticalTimeDenom) * time.Millisecond + block, err := proposal.NewBlockTemplate(b.chain, b.accountManager, nextBlockTime, warnDuration, criticalDuration) if err != nil { log.WithFields(log.Fields{"module": logModule, "error": err}).Error("failed on create NewBlockTemplate") continue diff --git a/proposal/proposal.go b/proposal/proposal.go index c754412e..847017b4 100644 --- a/proposal/proposal.go +++ b/proposal/proposal.go @@ -22,11 +22,15 @@ import ( const ( logModule = "mining" batchApplyNum = 64 + + timeoutOk = iota + 1 + timeoutWarn + timeoutCritical ) // NewBlockTemplate returns a new block template that is ready to be solved -func NewBlockTemplate(chain *protocol.Chain, accountManager *account.Manager, timestamp uint64, timeoutDuration time.Duration) (*types.Block, error) { - builder := newBlockBuilder(chain, accountManager, timestamp, timeoutDuration) +func NewBlockTemplate(chain *protocol.Chain, accountManager *account.Manager, timestamp uint64, warnDuration, criticalDuration time.Duration) (*types.Block, error) { + builder := newBlockBuilder(chain, accountManager, timestamp, warnDuration, criticalDuration) return builder.build() } @@ -38,12 +42,13 @@ type blockBuilder struct { txStatus *bc.TransactionStatus utxoView *state.UtxoViewpoint - timeoutCh <-chan time.Time - gasLeft int64 - timeoutFlag bool + warnTimeoutCh <-chan time.Time + criticalTimeoutCh <-chan time.Time + timeoutStatus uint8 + gasLeft int64 } -func newBlockBuilder(chain *protocol.Chain, accountManager *account.Manager, timestamp uint64, timeoutDuration time.Duration) *blockBuilder { +func newBlockBuilder(chain *protocol.Chain, accountManager *account.Manager, timestamp uint64, warnDuration, criticalDuration time.Duration) *blockBuilder { preBlockHeader := chain.BestBlockHeader() block := &types.Block{ BlockHeader: types.BlockHeader{ @@ -57,13 +62,15 @@ func newBlockBuilder(chain *protocol.Chain, accountManager *account.Manager, tim } builder := &blockBuilder{ - chain: chain, - accountManager: accountManager, - block: block, - txStatus: bc.NewTransactionStatus(), - utxoView: state.NewUtxoViewpoint(), - timeoutCh: time.After(timeoutDuration), - gasLeft: int64(consensus.ActiveNetParams.MaxBlockGas), + chain: chain, + accountManager: accountManager, + block: block, + txStatus: bc.NewTransactionStatus(), + utxoView: state.NewUtxoViewpoint(), + warnTimeoutCh: time.After(warnDuration), + criticalTimeoutCh: time.After(criticalDuration), + gasLeft: int64(consensus.ActiveNetParams.MaxBlockGas), + timeoutStatus: timeoutOk, } return builder } @@ -87,7 +94,7 @@ func (b *blockBuilder) applyCoinbaseTransaction() error { b.gasLeft -= gasState.GasUsed return nil } -func (b *blockBuilder) applyTransactions(txs []*types.Tx) error { +func (b *blockBuilder) applyTransactions(txs []*types.Tx, timeoutStatus uint8) error { tempTxs := []*types.Tx{} for i := 0; i < len(txs); i++ { if tempTxs = append(tempTxs, txs[i]); len(tempTxs) < batchApplyNum && i != len(txs)-1 { @@ -111,7 +118,7 @@ func (b *blockBuilder) applyTransactions(txs []*types.Tx) error { b.gasLeft = gasLeft tempTxs = []*types.Tx{} - if b.isTimeout() { + if b.getTimeoutStatus() >= timeoutStatus { break } } @@ -127,7 +134,7 @@ func (b *blockBuilder) applyTransactionFromPool() error { poolTxs[i] = txDesc.Tx } - return b.applyTransactions(poolTxs) + return b.applyTransactions(poolTxs, timeoutWarn) } func (b *blockBuilder) applyTransactionFromSubProtocol() error { @@ -136,18 +143,22 @@ func (b *blockBuilder) applyTransactionFromSubProtocol() error { return err } + isTimeout := func() bool { + return b.getTimeoutStatus() > timeoutOk + } + for i, p := range b.chain.SubProtocols() { - if b.gasLeft <= 0 || b.isTimeout() { + if b.gasLeft <= 0 || isTimeout() { break } - subTxs, err := p.BeforeProposalBlock(b.block.Transactions, cp, b.block.Height, b.gasLeft, b.isTimeout) + subTxs, err := p.BeforeProposalBlock(b.block.Transactions, cp, b.block.Height, b.gasLeft, isTimeout) if err != nil { log.WithFields(log.Fields{"module": logModule, "index": i, "error": err}).Error("failed on sub protocol txs package") continue } - if err := b.applyTransactions(subTxs); err != nil { + if err := b.applyTransactions(subTxs, timeoutCritical); err != nil { return err } } @@ -207,17 +218,20 @@ func (b *blockBuilder) createCoinbaseTx() (*types.Tx, error) { return createCoinbaseTxByReward(b.accountManager, b.block.Height, rewards) } -func (b *blockBuilder) isTimeout() bool { - if b.timeoutFlag { - return true +func (b *blockBuilder) getTimeoutStatus() uint8 { + if b.timeoutStatus == timeoutCritical { + return b.timeoutStatus } select { - case <-b.timeoutCh: - b.timeoutFlag = true + case <-b.criticalTimeoutCh: + b.timeoutStatus = timeoutCritical + case <-b.warnTimeoutCh: + b.timeoutStatus = timeoutWarn default: } - return b.timeoutFlag + + return b.timeoutStatus } func createCoinbaseTxByReward(accountManager *account.Manager, blockHeight uint64, rewards []state.CoinbaseReward) (tx *types.Tx, err error) { diff --git a/test/bench_blockchain_test.go b/test/bench_blockchain_test.go index 2d24dc7a..34271e6f 100644 --- a/test/bench_blockchain_test.go +++ b/test/bench_blockchain_test.go @@ -159,7 +159,7 @@ func InsertChain(chain *protocol.Chain, txPool *protocol.TxPool, txs []*types.Tx } } - block, err := proposal.NewBlockTemplate(chain, nil, uint64(time.Now().UnixNano()/1e6), time.Minute) + block, err := proposal.NewBlockTemplate(chain, nil, uint64(time.Now().UnixNano()/1e6), time.Minute, time.Minute) if err != nil { return err } diff --git a/test/performance/mining_test.go b/test/performance/mining_test.go index 72cb004e..d1729739 100644 --- a/test/performance/mining_test.go +++ b/test/performance/mining_test.go @@ -26,6 +26,6 @@ func BenchmarkNewBlockTpl(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - proposal.NewBlockTemplate(chain, accountManager, uint64(time.Now().UnixNano()/1e6), time.Minute) + proposal.NewBlockTemplate(chain, accountManager, uint64(time.Now().UnixNano()/1e6), time.Minute, time.Minute) } } -- 2.11.0