Skip to content

Commit d8d9dd7

Browse files
committed
[mint] deadline for mint block (#4487)
1 parent 56bfc0a commit d8d9dd7

File tree

7 files changed

+63
-7
lines changed

7 files changed

+63
-7
lines changed

blockchain/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ type (
7171
StreamingBlockBufferSize uint64 `yaml:"streamingBlockBufferSize"`
7272
// PersistStakingPatchBlock is the block to persist staking patch
7373
PersistStakingPatchBlock uint64 `yaml:"persistStakingPatchBlock"`
74+
// MintTimeout is the timeout for minting
75+
MintTimeout time.Duration `yaml:"-"`
7476
}
7577
)
7678

@@ -111,6 +113,7 @@ var (
111113
WorkingSetCacheSize: 20,
112114
StreamingBlockBufferSize: 200,
113115
PersistStakingPatchBlock: 19778037,
116+
MintTimeout: 1500 * time.Millisecond, // valued with block accept ttl - 500ms(tolerate network delay)
114117
}
115118

116119
// ErrConfig config error

chainservice/builder.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,11 @@ func (builder *Builder) createBlockchain(forSubChain, forTest bool) blockchain.B
486486
chainOpts = append(chainOpts, blockchain.BlockValidatorOption(builder.cs.factory))
487487
}
488488

489-
return blockchain.NewBlockchain(builder.cfg.Chain, builder.cfg.Genesis, builder.cs.blockdao, factory.NewMinter(builder.cs.factory, builder.cs.actpool), chainOpts...)
489+
var mintOpts []factory.MintOption
490+
if builder.cfg.Consensus.Scheme == config.RollDPoSScheme {
491+
mintOpts = append(mintOpts, factory.WithTimeoutOption(builder.cfg.Chain.MintTimeout))
492+
}
493+
return blockchain.NewBlockchain(builder.cfg.Chain, builder.cfg.Genesis, builder.cs.blockdao, factory.NewMinter(builder.cs.factory, builder.cs.actpool, mintOpts...), chainOpts...)
490494
}
491495

492496
func (builder *Builder) buildNodeInfoManager() error {

config/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ func New(configPaths []string, _plugins []string, validates ...Validate) (Config
164164
if err := cfg.Chain.SetProducerPrivKey(); err != nil {
165165
return Config{}, errors.Wrap(err, "failed to set producer private key")
166166
}
167+
// set default value for mint timeout
168+
cfg.Chain.MintTimeout = Default.Chain.MintTimeout
167169

168170
// set network master key to private key
169171
if cfg.Network.MasterKey == "" {

e2etest/local_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
"github.com/libp2p/go-libp2p-core/peer"
16+
"github.com/mohae/deepcopy"
1617
"github.com/multiformats/go-multiaddr"
1718
"github.com/stretchr/testify/require"
1819
"google.golang.org/protobuf/proto"
@@ -546,9 +547,10 @@ func TestStartExistingBlockchain(t *testing.T) {
546547
}
547548

548549
func newTestConfig() (config.Config, error) {
549-
cfg := config.Default
550+
cfg := deepcopy.Copy(config.Default).(config.Config)
550551
cfg.Chain.TrieDBPath = _triePath
551552
cfg.Chain.ChainDBPath = _dBPath
553+
cfg.Chain.MintTimeout = 0
552554
cfg.ActPool.MinGasPriceStr = "0"
553555
cfg.Consensus.Scheme = config.NOOPScheme
554556
cfg.Network.Port = testutil.RandomPort()

e2etest/staking_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"time"
1616

1717
"github.com/ethereum/go-ethereum/accounts/abi"
18+
"github.com/mohae/deepcopy"
1819
"github.com/stretchr/testify/require"
1920

2021
"github.com/iotexproject/go-pkgs/hash"
@@ -182,7 +183,7 @@ func TestStakingContract(t *testing.T) {
182183
}
183184
}
184185

185-
cfg := config.Default
186+
cfg := deepcopy.Copy(config.Default).(config.Config)
186187
initDBPaths(require, &cfg)
187188

188189
defer func() {
@@ -194,6 +195,7 @@ func TestStakingContract(t *testing.T) {
194195
cfg.ActPool.MinGasPriceStr = "0"
195196
cfg.Chain.TrieDBPatchFile = ""
196197
cfg.Chain.ProducerPrivKey = "a000000000000000000000000000000000000000000000000000000000000000"
198+
cfg.Chain.MintTimeout = 0
197199
cfg.Consensus.Scheme = config.RollDPoSScheme
198200
cfg.Genesis.NumDelegates = 1
199201
cfg.Genesis.NumSubEpochs = 10

state/factory/minter.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,45 @@ package factory
77

88
import (
99
"context"
10+
"time"
1011

1112
"github.com/iotexproject/iotex-core/v2/action"
13+
"github.com/iotexproject/iotex-core/v2/action/protocol"
1214
"github.com/iotexproject/iotex-core/v2/actpool"
1315
"github.com/iotexproject/iotex-core/v2/blockchain"
1416
"github.com/iotexproject/iotex-core/v2/blockchain/block"
1517
)
1618

19+
type MintOption func(*minter)
20+
21+
// WithTimeoutOption sets the timeout for NewBlockBuilder
22+
func WithTimeoutOption(timeout time.Duration) MintOption {
23+
return func(m *minter) {
24+
m.timeout = timeout
25+
}
26+
}
27+
1728
type minter struct {
18-
f Factory
19-
ap actpool.ActPool
29+
f Factory
30+
ap actpool.ActPool
31+
timeout time.Duration
2032
}
2133

2234
// NewMinter creates a wrapper instance
23-
func NewMinter(f Factory, ap actpool.ActPool) blockchain.BlockBuilderFactory {
24-
return &minter{f: f, ap: ap}
35+
func NewMinter(f Factory, ap actpool.ActPool, opts ...MintOption) blockchain.BlockBuilderFactory {
36+
m := &minter{f: f, ap: ap}
37+
for _, opt := range opts {
38+
opt(m)
39+
}
40+
return m
2541
}
2642

2743
// NewBlockBuilder implements the BlockMinter interface
2844
func (m *minter) NewBlockBuilder(ctx context.Context, sign func(action.Envelope) (*action.SealedEnvelope, error)) (*block.Builder, error) {
45+
if m.timeout > 0 {
46+
var cancel context.CancelFunc
47+
ctx, cancel = context.WithDeadline(ctx, protocol.MustGetBlockCtx(ctx).BlockTimeStamp.Add(m.timeout))
48+
defer cancel()
49+
}
2950
return m.f.NewBlockBuilder(ctx, m.ap, sign)
3051
}

state/factory/workingset.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package factory
88
import (
99
"context"
1010
"sort"
11+
"time"
1112

1213
"github.com/ethereum/go-ethereum/common"
1314
"github.com/iotexproject/go-pkgs/hash"
@@ -37,6 +38,13 @@ var (
3738
},
3839
[]string{"type"},
3940
)
41+
_mintAbility = prometheus.NewGaugeVec(
42+
prometheus.GaugeOpts{
43+
Name: "iotex_mint_ability",
44+
Help: "IoTeX Mint Ability",
45+
},
46+
[]string{"type"},
47+
)
4048

4149
errInvalidSystemActionLayout = errors.New("system action layout is invalid")
4250
errUnfoldTxContainer = errors.New("failed to unfold tx container")
@@ -45,6 +53,7 @@ var (
4553

4654
func init() {
4755
prometheus.MustRegister(_stateDBMtc)
56+
prometheus.MustRegister(_mintAbility)
4857
}
4958

5059
type (
@@ -564,10 +573,23 @@ func (ws *workingSet) pickAndRunActions(
564573
ctxWithBlockContext = ctx
565574
blkCtx = protocol.MustGetBlockCtx(ctx)
566575
fCtx = protocol.MustGetFeatureCtx(ctx)
576+
deadline *time.Time
577+
fullGas = blkCtx.GasLimit
567578
)
568579
if ap != nil {
580+
if dl, ok := ctx.Deadline(); ok {
581+
deadline = &dl
582+
}
569583
actionIterator := actioniterator.NewActionIterator(ap.PendingActionMap())
570584
for {
585+
if deadline != nil && time.Now().After(*deadline) {
586+
duration := time.Since(blkCtx.BlockTimeStamp)
587+
log.L().Warn("Stop processing actions due to deadline, please consider increasing hardware", zap.Time("deadline", *deadline), zap.Duration("duration", duration), zap.Int("actions", len(executedActions)), zap.Uint64("gas", fullGas-blkCtx.GasLimit))
588+
_mintAbility.WithLabelValues("action").Set(float64(len(executedActions)))
589+
_mintAbility.WithLabelValues("gas").Set(float64(fullGas - blkCtx.GasLimit))
590+
_mintAbility.WithLabelValues("duration").Set(float64(duration.Milliseconds()))
591+
break
592+
}
571593
nextAction, ok := actionIterator.Next()
572594
if !ok {
573595
break

0 commit comments

Comments
 (0)