Merge pull request #2829 from nspcc-dev/ms-per-block

TimePerBlock config
This commit is contained in:
Roman Khimov 2022-12-05 14:27:55 +07:00 committed by GitHub
commit b7518423d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 82 additions and 40 deletions

View file

@ -92,3 +92,13 @@ used instead (that also have a counter).
It's not a frequently used thing and it's easy to replace it, so removal of
old counters is scheduled for January-February 2023 (~0.100.X release).
## SecondsPerBlock protocol configuration
With 0.100.0 version SecondsPerBlock protocol configuration setting was
deprecated and replaced by a bit more generic and precise TimePerBlock
(allowing for subsecond time). An informational message is printed on node
startup to inform about this, it's very easy to deal with this configuration
change, just replace one line.
Removal of SecondsPerBlock is scheduled for May-June 2023 (~0.103.0 release).

View file

@ -2,7 +2,7 @@ ProtocolConfiguration:
Magic: 91414437
MaxTraceableBlocks: 2102400
InitialGASSupply: 52000000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 026fa34ec057d74c2fdf1a18e336d0bd597ea401a0b2ad57340d5c220d09f44086

View file

@ -2,7 +2,7 @@ ProtocolConfiguration:
Magic: 860833102
MaxTraceableBlocks: 2102400
InitialGASSupply: 52000000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 56753
MaxTraceableBlocks: 200000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 56753
MaxTraceableBlocks: 200000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 56753
MaxTraceableBlocks: 200000
SecondsPerBlock: 1
TimePerBlock: 1s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 56753
MaxTraceableBlocks: 200000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 56753
MaxTraceableBlocks: 200000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 56753
MaxTraceableBlocks: 200000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -2,7 +2,7 @@ ProtocolConfiguration:
Magic: 735783775
MaxTraceableBlocks: 2102400
InitialGASSupply: 52000000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 0337f5f45e5be5aeae4a919d0787fcb743656560949061d5b8b05509b85ffbfd53

View file

@ -5,7 +5,7 @@ ProtocolConfiguration:
MaxTraceableBlocks: 2102400
MaxTransactionsPerBlock: 5000
InitialGASSupply: 52000000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 42
MaxTraceableBlocks: 200000
SecondsPerBlock: 1
TimePerBlock: 100ms
MemPoolSize: 100
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -1,7 +1,7 @@
ProtocolConfiguration:
Magic: 42
MaxTraceableBlocks: 200000
SecondsPerBlock: 15
TimePerBlock: 15s
MemPoolSize: 50000
StandbyCommittee:
- 02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2

View file

@ -197,7 +197,7 @@ where:
enable `SessionBackedByMPT`, see `SessionBackedByMPT` documentation for more
details.
- `SessionExpirationTime` is a lifetime of iterator session in seconds. It is set
to `SecondsPerBlock` seconds by default and is relevant only if `SessionEnabled`
to `TimePerBlock` seconds by default and is relevant only if `SessionEnabled`
is set to `true`.
- `SessionBackedByMPT` is a flag forcing JSON-RPC server into using MPT-backed
storage for delayed iterator traversal. If `true`, then iterator resources got
@ -275,11 +275,12 @@ protocol-related settings described in the table below.
| RemoveUntraceableBlocks | `bool`| `false` | Denotes whether old blocks should be removed from cache and database. If enabled, then only the last `MaxTraceableBlocks` are stored and accessible to smart contracts. Old MPT data is also deleted in accordance with `GarbageCollectionPeriod` setting. If enabled along with `P2PStateExchangeExtensions`, then old blocks and MPT states will be removed up to the second latest state synchronisation point (see `StateSyncInterval`). |
| ReservedAttributes | `bool` | `false` | Allows to have reserved attributes range for experimental or private purposes. |
| SaveStorageBatch | `bool` | `false` | Enables storage batch saving before every persist. It is similar to StorageDump plugin for C# node. |
| SecondsPerBlock | `int` | `15` | Minimal time that should pass before next block is accepted. |
| SecondsPerBlock | `int` | `15` | Minimal time that should pass before next block is accepted. Deprecated: please use TimePerBlock setting (which overrides anything set here), SecondsPerBlock will be removed in future versions. |
| SeedList | `[]string` | [] | List of initial nodes addresses used to establish connectivity. |
| StandbyCommittee | `[]string` | [] | List of public keys of standby committee validators are chosen from. |
| StateRootInHeader | `bool` | `false` | Enables storing state root in block header. | Experimental protocol extension! |
| StateSyncInterval | `int` | `40000` | The number of blocks between state heights available for MPT state data synchronization. | `P2PStateExchangeExtensions` should be enabled to use this setting. |
| TimePerBlock | `Duration` | `15s` | Minimal (and targeted for) time interval between blocks. Must be an integer number of milliseconds. |
| ValidatorsCount | `int` | `0` | Number of validators set for the whole network lifetime, can't be set if `ValidatorsHistory` setting is used. |
| ValidatorsHistory | map[uint32]int | none | Number of consensus nodes to use after given height (see `CommitteeHistory` also). Heights where the change occurs must be divisible by the number of committee members at that height. Can't be used with `ValidatorsCount` not equal to zero. |
| VerifyBlocks | `bool` | `false` | Denotes whether to verify the received blocks. |

View file

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"sort"
"time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
@ -58,7 +59,10 @@ type (
// ReservedAttributes allows to have reserved attributes range for experimental or private purposes.
ReservedAttributes bool `yaml:"ReservedAttributes"`
// SaveStorageBatch enables storage batch saving before every persist.
SaveStorageBatch bool `yaml:"SaveStorageBatch"`
SaveStorageBatch bool `yaml:"SaveStorageBatch"`
// SecondsPerBlock is the time interval (in seconds) between blocks that consensus nodes work with.
//
// Deprecated: replaced by TimePerBlock, to be removed in future versions.
SecondsPerBlock int `yaml:"SecondsPerBlock"`
SeedList []string `yaml:"SeedList"`
StandbyCommittee []string `yaml:"StandbyCommittee"`
@ -67,7 +71,10 @@ type (
// StateSyncInterval is the number of blocks between state heights available for MPT state data synchronization.
// It is valid only if P2PStateExchangeExtensions are enabled.
StateSyncInterval int `yaml:"StateSyncInterval"`
ValidatorsCount int `yaml:"ValidatorsCount"`
// TimePerBlock is the time interval between blocks that consensus nodes work with.
// It must be an integer number of milliseconds.
TimePerBlock time.Duration `yaml:"TimePerBlock"`
ValidatorsCount int `yaml:"ValidatorsCount"`
// Validators stores history of changes to consensus node number (height: number).
ValidatorsHistory map[uint32]int `yaml:"ValidatorsHistory"`
// Whether to verify received blocks.
@ -92,6 +99,9 @@ func (p *ProtocolConfiguration) Validate() error {
if p.P2PStateExchangeExtensions && p.KeepOnlyLatestState && !p.RemoveUntraceableBlocks {
return fmt.Errorf("P2PStateExchangeExtensions can be enabled either on MPT-complete node (KeepOnlyLatestState=false) or on light GC-enabled node (RemoveUntraceableBlocks=true)")
}
if p.TimePerBlock%time.Millisecond != 0 {
return errors.New("TimePerBlock must be an integer number of milliseconds")
}
for name := range p.NativeUpdateHistories {
if !nativenames.IsValid(name) {
return fmt.Errorf("NativeActivations configuration section contains unexpected native contract name: %s", name)
@ -219,6 +229,7 @@ func (p *ProtocolConfiguration) Equals(o *ProtocolConfiguration) bool {
p.SecondsPerBlock != o.SecondsPerBlock ||
p.StateRootInHeader != o.StateRootInHeader ||
p.StateSyncInterval != o.StateSyncInterval ||
p.TimePerBlock != o.TimePerBlock ||
p.ValidatorsCount != o.ValidatorsCount ||
p.VerifyBlocks != o.VerifyBlocks ||
p.VerifyTransactions != o.VerifyTransactions ||

View file

@ -3,6 +3,7 @@ package config
import (
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/require"
)
@ -17,6 +18,14 @@ func TestProtocolConfigurationValidation(t *testing.T) {
P2PStateExchangeExtensions: true,
}
require.Error(t, p.Validate())
p = &ProtocolConfiguration{
StandbyCommittee: []string{
"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2",
},
ValidatorsCount: 1,
TimePerBlock: time.Microsecond,
}
require.Error(t, p.Validate())
p = &ProtocolConfiguration{
ValidatorsCount: 1,
}

View file

@ -480,7 +480,7 @@ func newTestServiceWithChain(t *testing.T, bc *core.Blockchain) *service {
ProtocolConfiguration: bc.GetConfig(),
RequestTx: func(...util.Uint256) {},
StopTxFlow: func() {},
TimePerBlock: time.Duration(bc.GetConfig().SecondsPerBlock) * time.Second,
TimePerBlock: bc.GetConfig().TimePerBlock,
Wallet: &config.Wallet{
Path: "./testdata/wallet1.json",
Password: "one",

View file

@ -55,7 +55,7 @@ const (
defaultMaxBlockSystemFee = 900000000000
defaultMaxTraceableBlocks = 2102400 // 1 year of 15s blocks
defaultMaxTransactionsPerBlock = 512
defaultSecondsPerBlock = 15
defaultTimePerBlock = 15 * time.Second
// HeaderVerificationGasLimit is the maximum amount of GAS for block header verification.
HeaderVerificationGasLimit = 3_00000000 // 3 GAS
defaultStateSyncInterval = 40000
@ -252,15 +252,21 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L
log.Info("MaxTransactionsPerBlock is not set or wrong, using default value",
zap.Uint16("MaxTransactionsPerBlock", cfg.MaxTransactionsPerBlock))
}
if cfg.SecondsPerBlock == 0 {
cfg.SecondsPerBlock = defaultSecondsPerBlock
log.Info("SecondsPerBlock is not set or wrong, using default value",
zap.Int("SecondsPerBlock", cfg.SecondsPerBlock))
if cfg.TimePerBlock <= 0 {
if cfg.SecondsPerBlock > 0 { //nolint:staticcheck // SA1019: cfg.SecondsPerBlock is deprecated
cfg.TimePerBlock = time.Duration(cfg.SecondsPerBlock) * time.Second //nolint:staticcheck // SA1019: cfg.SecondsPerBlock is deprecated
log.Info("TimePerBlock is not set, using deprecated SecondsPerBlock setting, consider updating your config",
zap.Duration("TimePerBlock", cfg.TimePerBlock))
} else {
cfg.TimePerBlock = defaultTimePerBlock
log.Info("TimePerBlock is not set or wrong, using default value",
zap.Duration("TimePerBlock", cfg.TimePerBlock))
}
}
if cfg.MaxValidUntilBlockIncrement == 0 {
const secondsPerDay = int(24 * time.Hour / time.Second)
const timePerDay = 24 * time.Hour
cfg.MaxValidUntilBlockIncrement = uint32(secondsPerDay / cfg.SecondsPerBlock)
cfg.MaxValidUntilBlockIncrement = uint32(timePerDay / cfg.TimePerBlock)
log.Info("MaxValidUntilBlockIncrement is not set or wrong, using default value",
zap.Uint32("MaxValidUntilBlockIncrement", cfg.MaxValidUntilBlockIncrement))
}
@ -2614,7 +2620,7 @@ func (bc *Blockchain) getFakeNextBlock(nextBlockHeight uint32) (*block.Block, er
if err != nil {
return nil, err
}
b.Timestamp = hdr.Timestamp + uint64(bc.config.SecondsPerBlock*int(time.Second/time.Millisecond))
b.Timestamp = hdr.Timestamp + uint64(bc.config.TimePerBlock/time.Millisecond)
return b, nil
}

View file

@ -4,6 +4,7 @@ import (
"encoding/hex"
"sort"
"testing"
"time"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
@ -22,9 +23,9 @@ const (
// We don't need a lot of traceable blocks for tests.
MaxTraceableBlocks = 1000
// SecondsPerBlock is the default SecondsPerBlock setting used for test chains.
// TimePerBlock is the default TimePerBlock setting used for test chains (1s).
// Usually blocks are created by tests bypassing this setting.
SecondsPerBlock = 1
TimePerBlock = time.Second
)
const singleValidatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY"
@ -117,7 +118,7 @@ func init() {
// NewSingle creates a new blockchain instance with a single validator and
// setups cleanup functions. The configuration used is with netmode.UnitTestNet
// magic and SecondsPerBlock/MaxTraceableBlocks options defined by constants in
// magic and TimePerBlock/MaxTraceableBlocks options defined by constants in
// this package. MemoryStore is used as the backend storage, so all of the chain
// contents is always in RAM. The Signer returned is the validator (and the committee at
// the same time).
@ -140,7 +141,7 @@ func NewSingleWithCustomConfigAndStore(t testing.TB, f func(cfg *config.Protocol
protoCfg := config.ProtocolConfiguration{
Magic: netmode.UnitTestNet,
MaxTraceableBlocks: MaxTraceableBlocks,
SecondsPerBlock: SecondsPerBlock,
TimePerBlock: TimePerBlock,
StandbyCommittee: []string{hex.EncodeToString(committeeAcc.PublicKey().Bytes())},
ValidatorsCount: 1,
VerifyBlocks: true,
@ -196,7 +197,7 @@ func NewMultiWithCustomConfigAndStoreNoCheck(t testing.TB, f func(*config.Protoc
protoCfg := config.ProtocolConfiguration{
Magic: netmode.UnitTestNet,
MaxTraceableBlocks: MaxTraceableBlocks,
SecondsPerBlock: SecondsPerBlock,
TimePerBlock: TimePerBlock,
StandbyCommittee: standByCommittee,
ValidatorsCount: 4,
VerifyBlocks: true,

View file

@ -89,6 +89,10 @@ type (
func NewServerConfig(cfg config.Config) ServerConfig {
appConfig := cfg.ApplicationConfiguration
protoConfig := cfg.ProtocolConfiguration
timePerBlock := protoConfig.TimePerBlock
if timePerBlock == 0 && protoConfig.SecondsPerBlock > 0 { //nolint:staticcheck // SA1019: protoConfig.SecondsPerBlock is deprecated
timePerBlock = time.Duration(protoConfig.SecondsPerBlock) * time.Second //nolint:staticcheck // SA1019: protoConfig.SecondsPerBlock is deprecated
}
return ServerConfig{
UserAgent: cfg.GenerateUserAgent(),
@ -105,7 +109,7 @@ func NewServerConfig(cfg config.Config) ServerConfig {
MaxPeers: appConfig.MaxPeers,
AttemptConnPeers: appConfig.AttemptConnPeers,
MinPeers: appConfig.MinPeers,
TimePerBlock: time.Duration(protoConfig.SecondsPerBlock) * time.Second,
TimePerBlock: timePerBlock,
OracleCfg: appConfig.Oracle,
P2PNotaryCfg: appConfig.P2PNotary,
StateRootCfg: appConfig.StateRoot,

View file

@ -205,7 +205,7 @@ func (p *TCPPeer) handleQueues() {
var p2pSkipCounter uint32
const p2pSkipDivisor = 4
var writeTimeout = time.Duration(p.server.config.SecondsPerBlock) * time.Second
var writeTimeout = p.server.TimePerBlock
for {
var msg []byte

View file

@ -2016,7 +2016,7 @@ func TestClient_Wait(t *testing.T) {
select {
case <-rcvr:
break waitloop
case <-time.NewTimer(time.Duration(chain.GetConfig().SecondsPerBlock) * time.Second).C:
case <-time.NewTimer(chain.GetConfig().TimePerBlock).C:
t.Fatal("transaction failed to be awaited")
}
}
@ -2092,7 +2092,7 @@ func TestWSClient_Wait(t *testing.T) {
require.Equal(t, vmstate.Halt, aer.VMState)
}
break waitloop
case <-time.NewTimer(time.Duration(chain.GetConfig().SecondsPerBlock) * time.Second).C:
case <-time.NewTimer(chain.GetConfig().TimePerBlock).C:
t.Fatalf("transaction from block %d failed to be awaited: deadline exceeded", b.Index)
}
}
@ -2254,7 +2254,7 @@ waitloop:
require.Equal(t, trigger.Application, aer.Trigger)
require.Equal(t, vmstate.Halt, aer.VMState)
break waitloop
case <-time.NewTimer(time.Duration(chain.GetConfig().SecondsPerBlock) * time.Second).C:
case <-time.NewTimer(chain.GetConfig().TimePerBlock).C:
t.Fatal("transaction failed to be awaited")
}
}

View file

@ -268,8 +268,8 @@ func New(chain Ledger, conf config.RPC, coreServer *network.Server,
protoCfg := chain.GetConfig()
if conf.SessionEnabled {
if conf.SessionExpirationTime <= 0 {
conf.SessionExpirationTime = protoCfg.SecondsPerBlock
log.Info("SessionExpirationTime is not set or wrong, setting default value", zap.Int("SessionExpirationTime", protoCfg.SecondsPerBlock))
conf.SessionExpirationTime = int(protoCfg.TimePerBlock / time.Second)
log.Info("SessionExpirationTime is not set or wrong, setting default value", zap.Int("SessionExpirationTime", conf.SessionExpirationTime))
}
if conf.SessionPoolSize <= 0 {
conf.SessionPoolSize = defaultSessionPoolSize
@ -706,7 +706,7 @@ func (s *Server) getVersion(_ params.Params) (interface{}, *neorpc.Error) {
Protocol: result.Protocol{
AddressVersion: address.NEO3Prefix,
Network: cfg.Magic,
MillisecondsPerBlock: cfg.SecondsPerBlock * 1000,
MillisecondsPerBlock: int(cfg.TimePerBlock / time.Millisecond),
MaxTraceableBlocks: cfg.MaxTraceableBlocks,
MaxValidUntilBlockIncrement: cfg.MaxValidUntilBlockIncrement,
MaxTransactionsPerBlock: cfg.MaxTransactionsPerBlock,

View file

@ -872,7 +872,7 @@ var rpcTestCases = map[string][]rpcTestCase{
cfg := e.chain.GetConfig()
require.EqualValues(t, address.NEO3Prefix, resp.Protocol.AddressVersion)
require.EqualValues(t, cfg.Magic, resp.Protocol.Network)
require.EqualValues(t, cfg.SecondsPerBlock*1000, resp.Protocol.MillisecondsPerBlock)
require.EqualValues(t, cfg.TimePerBlock/time.Millisecond, resp.Protocol.MillisecondsPerBlock)
require.EqualValues(t, cfg.MaxTraceableBlocks, resp.Protocol.MaxTraceableBlocks)
require.EqualValues(t, cfg.MaxValidUntilBlockIncrement, resp.Protocol.MaxValidUntilBlockIncrement)
require.EqualValues(t, cfg.MaxTransactionsPerBlock, resp.Protocol.MaxTransactionsPerBlock)

View file

@ -87,7 +87,7 @@ func New(cfg config.StateRoot, sm *stateroot.Module, log *zap.Logger, bc Ledger,
blockCh: make(chan *block.Block),
stopCh: make(chan struct{}),
done: make(chan struct{}),
timePerBlock: time.Duration(bcConf.SecondsPerBlock) * time.Second,
timePerBlock: bcConf.TimePerBlock,
maxRetries: voteValidEndInc,
relayExtensible: cb,
}