From 7589733017700d4d2e58fb7ca2f9d8d14275c377 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 6 Dec 2022 16:34:38 +0300 Subject: [PATCH] config: add a special Blockchain type to configure Blockchain And include some node-specific configurations there with backwards compatibility. Note that in the future we'll remove Ledger's fields from the ProtocolConfiguration and it'll be possible to access them in Blockchain directly (not via .Ledger). The other option tried was using two configuration types separately, but that incurs more changes to the codebase, single structure that behaves almost like the old one is better for backwards compatibility. Fixes #2676. --- ROADMAP.md | 10 +++ cli/server/server.go | 6 +- cli/vm/cli.go | 2 +- cli/vm/cli_test.go | 2 +- docs/node-configuration.md | 15 ++-- internal/contracts/contracts_test.go | 2 +- internal/fakechain/fakechain.go | 24 +++---- internal/testcli/executor.go | 4 +- pkg/config/application_config.go | 2 + pkg/config/config.go | 9 +++ pkg/config/ledger_config.go | 28 ++++++++ pkg/config/protocol_config.go | 10 +++ pkg/consensus/consensus.go | 4 +- pkg/consensus/consensus_test.go | 8 +-- pkg/core/basic_chain_test.go | 2 +- pkg/core/blockchain.go | 79 ++++++++++++---------- pkg/core/blockchain_core_test.go | 18 ++--- pkg/core/blockchain_neotest_test.go | 72 ++++++++++---------- pkg/core/chaindump/dump.go | 2 +- pkg/core/chaindump/dump_test.go | 12 ++-- pkg/core/helper_test.go | 8 +-- pkg/core/interop/context.go | 4 +- pkg/core/interop/contract/account_test.go | 2 +- pkg/core/native/invocation_test.go | 2 +- pkg/core/native/management_neotest_test.go | 2 +- pkg/core/native/native_test/gas_test.go | 2 +- pkg/core/native/native_test/ledger_test.go | 2 +- pkg/core/native/native_test/notary_test.go | 2 +- pkg/core/stateroot/module.go | 6 +- pkg/core/statesync/module.go | 10 +-- pkg/core/statesync/neotest_test.go | 24 +++---- pkg/neotest/chain/chain.go | 59 +++++++++------- pkg/network/helper_test.go | 2 +- pkg/network/server.go | 4 +- pkg/network/server_test.go | 17 ++--- pkg/services/notary/core_test.go | 2 +- pkg/services/oracle/oracle.go | 2 +- pkg/services/rpcsrv/server.go | 18 ++--- pkg/services/rpcsrv/server_helper_test.go | 2 +- pkg/services/stateroot/service.go | 2 +- pkg/services/stateroot/service_test.go | 2 +- scripts/gendump/main.go | 4 +- 42 files changed, 287 insertions(+), 202 deletions(-) create mode 100644 pkg/config/ledger_config.go diff --git a/ROADMAP.md b/ROADMAP.md index b57fcc7c8..43bc17c4c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -145,3 +145,13 @@ supported, but this support will eventually be removed. Removal of this compatibility code is scheduled for May-June 2023 (~0.103.0 release). + +## Node-specific configuration moved from Protocol to Application + +GarbageCollectionPeriod, KeepOnlyLatestState, RemoveUntraceableBlocks, +SaveStorageBatch and VerifyBlocks settings were moved from +ProtocolConfiguration to ApplicationConfiguration in version 0.100.0. Old +configurations are still supported. + +Removal of these options from ProtocolConfiguration is scheduled for May-June +2023 (~0.103.0 release). diff --git a/cli/server/server.go b/cli/server/server.go index c15c7bd13..399476905 100644 --- a/cli/server/server.go +++ b/cli/server/server.go @@ -235,7 +235,7 @@ func restoreDB(ctx *cli.Context) error { dumpDir := ctx.String("dump") if dumpDir != "" { - cfg.ProtocolConfiguration.SaveStorageBatch = true + cfg.ApplicationConfiguration.SaveStorageBatch = true } chain, prometheus, pprof, err := initBCWithMetrics(cfg, log) @@ -384,7 +384,7 @@ func mkConsensus(config config.Consensus, tpb time.Duration, chain *core.Blockch Logger: log, Broadcast: serv.BroadcastExtensible, Chain: chain, - ProtocolConfiguration: chain.GetConfig(), + ProtocolConfiguration: chain.GetConfig().ProtocolConfiguration, RequestTx: serv.RequestTx, StopTxFlow: serv.StopTxFlow, Wallet: config.UnlockWallet, @@ -658,7 +658,7 @@ func initBlockChain(cfg config.Config, log *zap.Logger) (*core.Blockchain, stora return nil, nil, cli.NewExitError(fmt.Errorf("could not initialize storage: %w", err), 1) } - chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, log) + chain, err := core.NewBlockchain(store, cfg.Blockchain(), log) if err != nil { errText := "could not initialize blockchain: %w" errArgs := []interface{}{err} diff --git a/cli/vm/cli.go b/cli/vm/cli.go index 0747473ea..f6d1d1f82 100644 --- a/cli/vm/cli.go +++ b/cli/vm/cli.go @@ -468,7 +468,7 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg onExit(i) } - chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, fLog) + chain, err := core.NewBlockchain(store, cfg.Blockchain(), fLog) if err != nil { return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1) } diff --git a/cli/vm/cli_test.go b/cli/vm/cli_test.go index a7ecdc957..2b6e7db45 100644 --- a/cli/vm/cli_test.go +++ b/cli/vm/cli_test.go @@ -122,7 +122,7 @@ func newTestVMClIWithState(t *testing.T) *executor { } store, err := storage.NewLevelDBStore(opts) require.NoError(t, err) - customConfig := func(c *config.ProtocolConfiguration) { + customConfig := func(c *config.Blockchain) { c.StateRootInHeader = true // Need for P2PStateExchangeExtensions check. c.P2PSigExtensions = true // Need for basic chain initializer. } diff --git a/docs/node-configuration.md b/docs/node-configuration.md index 2bfe30ec5..da82efd2a 100644 --- a/docs/node-configuration.md +++ b/docs/node-configuration.md @@ -24,6 +24,8 @@ node-related settings described in the table below. | DialTimeout | `int64` | `0` | Maximum duration a single dial may take in seconds. Warning: this field is deprecated and moved to `P2P` section. | | ExtensiblePoolSize | `int` | `20` | Maximum amount of the extensible payloads from a single sender stored in a local pool. Warning: this field is deprecated and moved to `P2P` section. | | LogLevel | `string` | "info" | Minimal logged messages level (can be "debug", "info", "warn", "error", "dpanic", "panic" or "fatal"). | +| GarbageCollectionPeriod | `uint32` | 10000 | Controls MPT garbage collection interval (in blocks) for configurations with `RemoveUntraceableBlocks` enabled and `KeepOnlyLatestState` disabled. In this mode the node stores a number of MPT trees (corresponding to `MaxTraceableBlocks` and `StateSyncInterval`), but the DB needs to be clean from old entries from time to time. Doing it too often will cause too much processing overhead, doing it too rarely will leave more useless data in the DB. | +| KeepOnlyLatestState | `bool` | `false` | Specifies if MPT should only store the latest state (or a set of latest states, see `P2PStateExchangeExtensions` section in the ProtocolConfiguration for details). If true, DB size will be smaller, but older roots won't be accessible. This value should remain the same for the same database. | | | LogPath | `string` | "", so only console logging | File path where to store node logs. | | MaxPeers | `int` | `100` | Maximum numbers of peers that can be connected to the server. Warning: this field is deprecated and moved to `P2P` section. | | MinPeers | `int` | `5` | Minimum number of peers for normal operation; when the node has less than this number of peers it tries to connect with some new ones. Warning: this field is deprecated and moved to `P2P` section. | @@ -38,9 +40,12 @@ node-related settings described in the table below. | ProtoTickInterval | `int64` | `5` | Duration in seconds between protocol ticks with each connected peer. Warning: this field is deprecated and moved to `P2P` section. | | Relay | `bool` | `true` | Determines whether the server is forwarding its inventory. | | Consensus | [Consensus Configuration](#Consensus-Configuration) | | Describes consensus (dBFT) configuration. See the [Consensus Configuration](#Consensus-Configuration) for details. | +| 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` protocol extension, then old blocks and MPT states will be removed up to the second latest state synchronisation point (see `StateSyncInterval`). | | RPC | [RPC Configuration](#RPC-Configuration) | | Describes [RPC subsystem](rpc.md) configuration. See the [RPC Configuration](#RPC-Configuration) for details. | +| SaveStorageBatch | `bool` | `false` | Enables storage batch saving before every persist. It is similar to StorageDump plugin for C# node. | | StateRoot | [State Root Configuration](#State-Root-Configuration) | | State root module configuration. See the [State Root Configuration](#State-Root-Configuration) section for details. | | UnlockWallet | [Unlock Wallet Configuration](#Unlock-Wallet-Configuration) | | Node wallet configuration used for consensus (dBFT) operation. See the [Unlock Wallet Configuration](#Unlock-Wallet-Configuration) section for details. This section is deprecated and replaced by Consensus, it only exists for compatibility with old configuration files, but will be removed in future node versions. | +| VerifyBlocks | `bool` | `false` | Denotes whether to verify the received blocks. | ### P2P Configuration @@ -335,9 +340,9 @@ protocol-related settings described in the table below. | Section | Type | Default value | Description | Notes | | --- | --- | --- | --- | --- | | CommitteeHistory | map[uint32]int | none | Number of committee members after the given height, for example `{0: 1, 20: 4}` sets up a chain with one committee member since the genesis and then changes the setting to 4 committee members at the height of 20. `StandbyCommittee` committee setting must have the number of keys equal or exceeding the highest value in this option. Blocks numbers where the change happens must be divisible by the old and by the new values simultaneously. If not set, committee size is derived from the `StandbyCommittee` setting and never changes. | -| GarbageCollectionPeriod | `uint32` | 10000 | Controls MPT garbage collection interval (in blocks) for configurations with `RemoveUntraceableBlocks` enabled and `KeepOnlyLatestState` disabled. In this mode the node stores a number of MPT trees (corresponding to `MaxTraceableBlocks` and `StateSyncInterval`), but the DB needs to be clean from old entries from time to time. Doing it too often will cause too much processing overhead, doing it too rarely will leave more useless data in the DB. | +| GarbageCollectionPeriod | `uint32` | 10000 | Controls MPT garbage collection interval (in blocks) for configurations with `RemoveUntraceableBlocks` enabled and `KeepOnlyLatestState` disabled. In this mode the node stores a number of MPT trees (corresponding to `MaxTraceableBlocks` and `StateSyncInterval`), but the DB needs to be clean from old entries from time to time. Doing it too often will cause too much processing overhead, doing it too rarely will leave more useless data in the DB. This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, ApplicationConfiguration is prioritized over this one. | | Hardforks | `map[string]uint32` | [] | The set of incompatible changes that affect node behaviour starting from the specified height. The default value is an empty set which should be interpreted as "each known hard-fork is applied from the zero blockchain height". The list of valid hard-fork names:
• `Aspidochelone` represents hard-fork introduced in [#2469](https://github.com/nspcc-dev/neo-go/pull/2469) (ported from the [reference](https://github.com/neo-project/neo/pull/2712)). It adjusts the prices of `System.Contract.CreateStandardAccount` and `System.Contract.CreateMultisigAccount` interops so that the resulting prices are in accordance with `sha256` method of native `CryptoLib` contract. `Aspidochelone` is also includes [#2519](https://github.com/nspcc-dev/neo-go/pull/2519) (ported from the [reference](https://github.com/neo-project/neo/pull/2749)). It adjusts the price of `System.Runtime.GetRandom` interop and fixes its vulnerability. | -| KeepOnlyLatestState | `bool` | `false` | Specifies if MPT should only store the latest state (or a set of latest states, see `P2PStateExcangeExtensions` section for details). If true, DB size will be smaller, but older roots won't be accessible. This value should remain the same for the same database. | | +| KeepOnlyLatestState | `bool` | `false` | Specifies if MPT should only store the latest state (or a set of latest states, see `P2PStateExcangeExtensions` section for details). If true, DB size will be smaller, but older roots won't be accessible. This value should remain the same for the same database. | This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, setting any of them to true enables the function. | | Magic | `uint32` | `0` | Magic number which uniquely identifies Neo network. | | MaxBlockSize | `uint32` | `262144` | Maximum block size in bytes. | | MaxBlockSystemFee | `int64` | `900000000000` | Maximum overall transactions system fee per block. | @@ -349,9 +354,9 @@ protocol-related settings described in the table below. | P2PNotaryRequestPayloadPoolSize | `int` | `1000` | Size of the node's P2P Notary request payloads memory pool where P2P Notary requests are stored before main or fallback transaction is completed and added to the chain.
This option is valid only if `P2PSigExtensions` are enabled. | Not supported by the C# node, thus may affect heterogeneous networks functionality. | | P2PSigExtensions | `bool` | `false` | Enables following additional Notary service related logic:
• Transaction attributes `NotValidBefore`, `Conflicts` and `NotaryAssisted`
• Network payload of the `P2PNotaryRequest` type
• Native `Notary` contract
• Notary node module | Not supported by the C# node, thus may affect heterogeneous networks functionality. | | P2PStateExchangeExtensions | `bool` | `false` | Enables the following P2P MPT state data exchange logic:
• `StateSyncInterval` protocol setting
• P2P commands `GetMPTDataCMD` and `MPTDataCMD` | Not supported by the C# node, thus may affect heterogeneous networks functionality. Can be supported either on MPT-complete node (`KeepOnlyLatestState`=`false`) or on light GC-enabled node (`RemoveUntraceableBlocks=true`) in which case `KeepOnlyLatestState` setting doesn't change the behavior, an appropriate set of MPTs is always stored (see `RemoveUntraceableBlocks`). | -| 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`). | +| 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`). | This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, setting any of them to true enables the function. | | 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. | +| SaveStorageBatch | `bool` | `false` | Enables storage batch saving before every persist. It is similar to StorageDump plugin for C# node. | This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, setting any of them to true enables the function. | | 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. | @@ -360,5 +365,5 @@ protocol-related settings described in the table below. | 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. | +| VerifyBlocks | `bool` | `false` | Denotes whether to verify the received blocks. | This setting is deprecated in favor of the same setting in the ApplicationConfiguration and will be removed in future node versions. If both settings are used, setting any of them to true enables the function. | | VerifyTransactions | `bool` | `false` | Denotes whether to verify transactions in the received blocks. | diff --git a/internal/contracts/contracts_test.go b/internal/contracts/contracts_test.go index 743bbb234..52fe24baa 100644 --- a/internal/contracts/contracts_test.go +++ b/internal/contracts/contracts_test.go @@ -65,7 +65,7 @@ func generateOracleContract(t *testing.T, saveState bool) { // native hashes and saves the generated NEF and manifest to `management_contract` folder. // Set `saveState` flag to true and run the test to rewrite NEF and manifest files. func generateManagementHelperContracts(t *testing.T, saveState bool) { - bc, validator, committee := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, validator, committee := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, validator, committee) diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 4ba989fdc..96296ac45 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -23,7 +23,7 @@ import ( // FakeChain implements the Blockchainer interface, but does not provide real functionality. type FakeChain struct { - config.ProtocolConfiguration + config.Blockchain *mempool.Pool blocksCh []chan *block.Block Blockheight uint32 @@ -56,19 +56,19 @@ func NewFakeChain() *FakeChain { } // NewFakeChainWithCustomCfg returns a new FakeChain structure with the specified protocol configuration. -func NewFakeChainWithCustomCfg(protocolCfg func(c *config.ProtocolConfiguration)) *FakeChain { - cfg := config.ProtocolConfiguration{Magic: netmode.UnitTestNet, P2PNotaryRequestPayloadPoolSize: 10} +func NewFakeChainWithCustomCfg(protocolCfg func(c *config.Blockchain)) *FakeChain { + cfg := config.Blockchain{ProtocolConfiguration: config.ProtocolConfiguration{Magic: netmode.UnitTestNet, P2PNotaryRequestPayloadPoolSize: 10}} if protocolCfg != nil { protocolCfg(&cfg) } return &FakeChain{ - Pool: mempool.New(10, 0, false), - PoolTxF: func(*transaction.Transaction) error { return nil }, - poolTxWithData: func(*transaction.Transaction, interface{}, *mempool.Pool) error { return nil }, - blocks: make(map[util.Uint256]*block.Block), - hdrHashes: make(map[uint32]util.Uint256), - txs: make(map[util.Uint256]*transaction.Transaction), - ProtocolConfiguration: cfg, + Pool: mempool.New(10, 0, false), + PoolTxF: func(*transaction.Transaction) error { return nil }, + poolTxWithData: func(*transaction.Transaction, interface{}, *mempool.Pool) error { return nil }, + blocks: make(map[util.Uint256]*block.Block), + hdrHashes: make(map[uint32]util.Uint256), + txs: make(map[util.Uint256]*transaction.Transaction), + Blockchain: cfg, } } @@ -159,8 +159,8 @@ func (chain *FakeChain) RegisterPostBlock(f func(func(*transaction.Transaction, } // GetConfig implements the Blockchainer interface. -func (chain *FakeChain) GetConfig() config.ProtocolConfiguration { - return chain.ProtocolConfiguration +func (chain *FakeChain) GetConfig() config.Blockchain { + return chain.Blockchain } // CalculateClaimable implements the Blockchainer interface. diff --git a/internal/testcli/executor.go b/internal/testcli/executor.go index 440704f0b..ea6749059 100644 --- a/internal/testcli/executor.go +++ b/internal/testcli/executor.go @@ -139,7 +139,7 @@ func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch memoryStore := storage.NewMemoryStore() logger := zaptest.NewLogger(t) - chain, err := core.NewBlockchain(memoryStore, cfg.ProtocolConfiguration, logger) + chain, err := core.NewBlockchain(memoryStore, cfg.Blockchain(), logger) require.NoError(t, err, "could not create chain") if run { @@ -155,7 +155,7 @@ func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch Logger: zap.NewNop(), Broadcast: netSrv.BroadcastExtensible, Chain: chain, - ProtocolConfiguration: chain.GetConfig(), + ProtocolConfiguration: cfg.ProtocolConfiguration, RequestTx: netSrv.RequestTx, StopTxFlow: netSrv.StopTxFlow, Wallet: cfg.ApplicationConfiguration.Consensus.UnlockWallet, diff --git a/pkg/config/application_config.go b/pkg/config/application_config.go index 85c520cdc..1d9496ee9 100644 --- a/pkg/config/application_config.go +++ b/pkg/config/application_config.go @@ -12,6 +12,8 @@ import ( // ApplicationConfiguration config specific to the node. type ApplicationConfiguration struct { + Ledger `yaml:",inline"` + // Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions. Address *string `yaml:"Address,omitempty"` // Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions. diff --git a/pkg/config/config.go b/pkg/config/config.go index ab6a4c5f6..094eba209 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -35,6 +35,15 @@ func (c Config) GenerateUserAgent() string { return fmt.Sprintf(UserAgentFormat, Version) } +// Blockchain generates a Blockchain configuration based on Protocol and +// Application settings. +func (c Config) Blockchain() Blockchain { + return Blockchain{ + ProtocolConfiguration: c.ProtocolConfiguration, + Ledger: c.ApplicationConfiguration.Ledger, + } +} + // Load attempts to load the config from the given // path for the given netMode. func Load(path string, netMode netmode.Magic) (Config, error) { diff --git a/pkg/config/ledger_config.go b/pkg/config/ledger_config.go new file mode 100644 index 000000000..02b4c90d4 --- /dev/null +++ b/pkg/config/ledger_config.go @@ -0,0 +1,28 @@ +package config + +// Ledger contains core node-specific settings that are not +// a part of the ProtocolConfiguration (which is common for every node on the +// network). +type Ledger struct { + // GarbageCollectionPeriod sets the number of blocks to wait before + // starting the next MPT garbage collection cycle when RemoveUntraceableBlocks + // option is used. + GarbageCollectionPeriod uint32 `yaml:"GarbageCollectionPeriod"` + // KeepOnlyLatestState specifies if MPT should only store the latest state. + // If true, DB size will be smaller, but older roots won't be accessible. + // This value should remain the same for the same database. + KeepOnlyLatestState bool `yaml:"KeepOnlyLatestState"` + // RemoveUntraceableBlocks specifies if old data should be removed. + RemoveUntraceableBlocks bool `yaml:"RemoveUntraceableBlocks"` + // SaveStorageBatch enables storage batch saving before every persist. + SaveStorageBatch bool `yaml:"SaveStorageBatch"` + // VerifyBlocks controls block verification checks (including cryptography). + VerifyBlocks bool `yaml:"VerifyBlocks"` +} + +// Blockchain is a set of settings for core.Blockchain to use, it includes protocol +// settings and local node-specific ones. +type Blockchain struct { + ProtocolConfiguration + Ledger +} diff --git a/pkg/config/protocol_config.go b/pkg/config/protocol_config.go index 014a2e288..653f1a6e2 100644 --- a/pkg/config/protocol_config.go +++ b/pkg/config/protocol_config.go @@ -19,6 +19,8 @@ type ( // GarbageCollectionPeriod sets the number of blocks to wait before // starting the next MPT garbage collection cycle when RemoveUntraceableBlocks // option is used. + // + // Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions. GarbageCollectionPeriod uint32 `yaml:"GarbageCollectionPeriod"` Magic netmode.Magic `yaml:"Magic"` @@ -35,8 +37,12 @@ type ( // KeepOnlyLatestState specifies if MPT should only store the latest state. // If true, DB size will be smaller, but older roots won't be accessible. // This value should remain the same for the same database. + // + // Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions. KeepOnlyLatestState bool `yaml:"KeepOnlyLatestState"` // RemoveUntraceableBlocks specifies if old data should be removed. + // + // Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions. RemoveUntraceableBlocks bool `yaml:"RemoveUntraceableBlocks"` // MaxBlockSize is the maximum block size in bytes. MaxBlockSize uint32 `yaml:"MaxBlockSize"` @@ -59,6 +65,8 @@ 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. + // + // Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions. SaveStorageBatch bool `yaml:"SaveStorageBatch"` // SecondsPerBlock is the time interval (in seconds) between blocks that consensus nodes work with. // @@ -78,6 +86,8 @@ type ( // Validators stores history of changes to consensus node number (height: number). ValidatorsHistory map[uint32]int `yaml:"ValidatorsHistory"` // Whether to verify received blocks. + // + // Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions. VerifyBlocks bool `yaml:"VerifyBlocks"` // Whether to verify transactions in the received blocks. VerifyTransactions bool `yaml:"VerifyTransactions"` diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 7378f4c77..a2833ac64 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -44,7 +44,7 @@ const nsInMs = 1000000 type Ledger interface { AddBlock(block *coreb.Block) error ApplyPolicyToTxSet([]*transaction.Transaction) []*transaction.Transaction - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetMemPool() *mempool.Pool GetNextBlockValidators() ([]*keys.PublicKey, error) GetStateRoot(height uint32) (*state.MPTRoot, error) @@ -708,7 +708,7 @@ func (s *service) newBlockFromContext(ctx *dbft.Context) block.Block { var validators keys.PublicKeys var err error - cfg := s.Chain.GetConfig() + cfg := s.Chain.GetConfig().ProtocolConfiguration if cfg.ShouldUpdateCommitteeAt(ctx.BlockIndex) { validators, err = s.Chain.GetValidators() } else { diff --git a/pkg/consensus/consensus_test.go b/pkg/consensus/consensus_test.go index 996f147a4..8626527e9 100644 --- a/pkg/consensus/consensus_test.go +++ b/pkg/consensus/consensus_test.go @@ -50,7 +50,7 @@ func TestNewWatchingService(t *testing.T) { Logger: zaptest.NewLogger(t), Broadcast: func(*npayload.Extensible) {}, Chain: bc, - ProtocolConfiguration: bc.GetConfig(), + ProtocolConfiguration: bc.GetConfig().ProtocolConfiguration, RequestTx: func(...util.Uint256) {}, StopTxFlow: func() {}, TimePerBlock: bc.GetConfig().TimePerBlock, @@ -495,7 +495,7 @@ func newTestServiceWithChain(t *testing.T, bc *core.Blockchain) *service { Logger: zaptest.NewLogger(t), Broadcast: func(*npayload.Extensible) {}, Chain: bc, - ProtocolConfiguration: bc.GetConfig(), + ProtocolConfiguration: bc.GetConfig().ProtocolConfiguration, RequestTx: func(...util.Uint256) {}, StopTxFlow: func() {}, TimePerBlock: bc.GetConfig().TimePerBlock, @@ -519,7 +519,7 @@ func newSingleTestChain(t *testing.T) *core.Blockchain { cfg, err := config.LoadFile(configPath) require.NoError(t, err, "could not load config") - chain, err := core.NewBlockchain(storage.NewMemoryStore(), cfg.ProtocolConfiguration, zaptest.NewLogger(t)) + chain, err := core.NewBlockchain(storage.NewMemoryStore(), cfg.Blockchain(), zaptest.NewLogger(t)) require.NoError(t, err, "could not create chain") go chain.Run() @@ -532,7 +532,7 @@ func newTestChain(t *testing.T, stateRootInHeader bool) *core.Blockchain { require.NoError(t, err) unitTestNetCfg.ProtocolConfiguration.StateRootInHeader = stateRootInHeader - chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.ProtocolConfiguration, zaptest.NewLogger(t)) + chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.Blockchain(), zaptest.NewLogger(t)) require.NoError(t, err) go chain.Run() diff --git a/pkg/core/basic_chain_test.go b/pkg/core/basic_chain_test.go index f483eb03f..91056576e 100644 --- a/pkg/core/basic_chain_test.go +++ b/pkg/core/basic_chain_test.go @@ -37,7 +37,7 @@ var ( func TestCreateBasicChain(t *testing.T) { const saveChain = false - bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(cfg *config.ProtocolConfiguration) { + bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(cfg *config.Blockchain) { cfg.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, validators, committee) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index e751ca666..fde23de07 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -116,7 +116,7 @@ var ( type Blockchain struct { HeaderHashes - config config.ProtocolConfiguration + config config.Blockchain // The only way chain state changes is by adding blocks, so we can't // allow concurrent block additions. It differs from the next lock in @@ -218,11 +218,12 @@ type transferData struct { // NewBlockchain returns a new blockchain object the will use the // given Store as its underlying storage. For it to work correctly you need // to spawn a goroutine for its Run method after this initialization. -func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.Logger) (*Blockchain, error) { +func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger) (*Blockchain, error) { if log == nil { return nil, errors.New("empty logger") } + // Protocol configuration fixups/checks. if cfg.InitialGASSupply <= 0 { cfg.InitialGASSupply = fixedn.Fixed8(defaultInitialGAS) log.Info("initial gas supply is not set or wrong, setting default value", zap.String("InitialGASSupply", cfg.InitialGASSupply.String())) @@ -280,10 +281,6 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L zap.Int("StateSyncInterval", cfg.StateSyncInterval)) } } - if cfg.RemoveUntraceableBlocks && cfg.GarbageCollectionPeriod == 0 { - cfg.GarbageCollectionPeriod = defaultGCPeriod - log.Info("GarbageCollectionPeriod is not set or wrong, using default value", zap.Uint32("GarbageCollectionPeriod", cfg.GarbageCollectionPeriod)) - } if len(cfg.NativeUpdateHistories) == 0 { cfg.NativeUpdateHistories = map[string][]uint32{} log.Info("NativeActivations are not set, using default values") @@ -292,6 +289,20 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L cfg.Hardforks = map[string]uint32{} log.Info("Hardforks are not set, using default value") } + // Compatibility with the old ProtocolConfiguration. + if cfg.ProtocolConfiguration.GarbageCollectionPeriod > 0 && cfg.Ledger.GarbageCollectionPeriod == 0 { //nolint:staticcheck // SA1019: cfg.ProtocolConfiguration.GarbageCollectionPeriod is deprecated + cfg.Ledger.GarbageCollectionPeriod = cfg.ProtocolConfiguration.GarbageCollectionPeriod //nolint:staticcheck // SA1019: cfg.ProtocolConfiguration.GarbageCollectionPeriod is deprecated + } + cfg.Ledger.KeepOnlyLatestState = cfg.Ledger.KeepOnlyLatestState || cfg.ProtocolConfiguration.KeepOnlyLatestState //nolint:staticcheck // SA1019: cfg.ProtocolConfiguration.KeepOnlyLatestState is deprecated + cfg.Ledger.RemoveUntraceableBlocks = cfg.Ledger.RemoveUntraceableBlocks || cfg.ProtocolConfiguration.RemoveUntraceableBlocks //nolint:staticcheck // SA1019: cfg.ProtocolConfiguration.RemoveUntraceableBlocks is deprecated + cfg.Ledger.SaveStorageBatch = cfg.Ledger.SaveStorageBatch || cfg.ProtocolConfiguration.SaveStorageBatch //nolint:staticcheck // SA1019: cfg.ProtocolConfiguration.SaveStorageBatch is deprecated + cfg.Ledger.VerifyBlocks = cfg.Ledger.VerifyBlocks || cfg.ProtocolConfiguration.VerifyBlocks //nolint:staticcheck // SA1019: cfg.ProtocolConfiguration.VerifyBlocks is deprecated + + // Local config consistency checks. + if cfg.Ledger.RemoveUntraceableBlocks && cfg.Ledger.GarbageCollectionPeriod == 0 { + cfg.Ledger.GarbageCollectionPeriod = defaultGCPeriod + log.Info("GarbageCollectionPeriod is not set or wrong, using default value", zap.Uint32("GarbageCollectionPeriod", cfg.Ledger.GarbageCollectionPeriod)) + } bc := &Blockchain{ config: cfg, dao: dao.NewSimple(s, cfg.StateRootInHeader, cfg.P2PSigExtensions), @@ -304,10 +315,10 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L events: make(chan bcEvent), subCh: make(chan interface{}), unsubCh: make(chan interface{}), - contracts: *native.NewContracts(cfg), + contracts: *native.NewContracts(cfg.ProtocolConfiguration), } - bc.stateRoot = stateroot.NewModule(bc.GetConfig(), bc.VerifyWitness, bc.log, bc.dao.Store) + bc.stateRoot = stateroot.NewModule(cfg, bc.VerifyWitness, bc.log, bc.dao.Store) bc.contracts.Designate.StateRootService = bc.stateRoot if err := bc.init(); err != nil { @@ -370,13 +381,13 @@ func (bc *Blockchain) init() error { StateRootInHeader: bc.config.StateRootInHeader, P2PSigExtensions: bc.config.P2PSigExtensions, P2PStateExchangeExtensions: bc.config.P2PStateExchangeExtensions, - KeepOnlyLatestState: bc.config.KeepOnlyLatestState, + KeepOnlyLatestState: bc.config.Ledger.KeepOnlyLatestState, Value: version, } bc.dao.PutVersion(ver) bc.dao.Version = ver bc.persistent.Version = ver - genesisBlock, err := CreateGenesisBlock(bc.config) + genesisBlock, err := CreateGenesisBlock(bc.config.ProtocolConfiguration) if err != nil { return err } @@ -401,9 +412,9 @@ func (bc *Blockchain) init() error { return fmt.Errorf("P2PStateExchangeExtensions setting mismatch (old=%t, new=%t)", ver.P2PStateExchangeExtensions, bc.config.P2PStateExchangeExtensions) } - if ver.KeepOnlyLatestState != bc.config.KeepOnlyLatestState { + if ver.KeepOnlyLatestState != bc.config.Ledger.KeepOnlyLatestState { return fmt.Errorf("KeepOnlyLatestState setting mismatch (old=%v, new=%v)", - ver.KeepOnlyLatestState, bc.config.KeepOnlyLatestState) + ver.KeepOnlyLatestState, bc.config.Ledger.KeepOnlyLatestState) } bc.dao.Version = ver bc.persistent.Version = ver @@ -432,7 +443,7 @@ func (bc *Blockchain) init() error { if (stateChStage[0] & stateResetBit) != 0 { return bc.resetStateInternal(stateSyncPoint, stateChangeStage(stateChStage[0]&(^stateResetBit))) } - if !(bc.GetConfig().P2PStateExchangeExtensions && bc.GetConfig().RemoveUntraceableBlocks) { + if !(bc.config.P2PStateExchangeExtensions && bc.config.Ledger.RemoveUntraceableBlocks) { return errors.New("state jump was not completed, but P2PStateExchangeExtensions are disabled or archival node capability is on. " + "To start an archival node drop the database manually and restart the node") } @@ -647,10 +658,10 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) bc.log.Info("chain is at the proper state", zap.Uint32("height", height)) return nil } - if bc.config.KeepOnlyLatestState { + if bc.config.Ledger.KeepOnlyLatestState { return fmt.Errorf("KeepOnlyLatestState is enabled, state for height %d is outdated and removed from the storage", height) } - if bc.config.RemoveUntraceableBlocks && currHeight >= bc.config.MaxTraceableBlocks { + if bc.config.Ledger.RemoveUntraceableBlocks && currHeight >= bc.config.MaxTraceableBlocks { return fmt.Errorf("RemoveUntraceableBlocks is enabled, a necessary batch of traceable blocks has already been removed") } } @@ -727,7 +738,7 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) pStorageStart := p var mode = mpt.ModeAll - if bc.config.RemoveUntraceableBlocks { + if bc.config.Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeGCFlag } trieStore := mpt.NewTrieStore(sr.Root, mode, cache.Store) @@ -919,14 +930,14 @@ func (bc *Blockchain) Run() { var oldPersisted uint32 var gcDur time.Duration - if bc.config.RemoveUntraceableBlocks { + if bc.config.Ledger.RemoveUntraceableBlocks { oldPersisted = atomic.LoadUint32(&bc.persistedHeight) } dur, err := bc.persist(nextSync) if err != nil { bc.log.Warn("failed to persist blockchain", zap.Error(err)) } - if bc.config.RemoveUntraceableBlocks { + if bc.config.Ledger.RemoveUntraceableBlocks { gcDur = bc.tryRunGC(oldPersisted) } nextSync = dur > persistInterval*2 @@ -955,14 +966,14 @@ func (bc *Blockchain) tryRunGC(oldHeight uint32) time.Duration { } } // Always round to the GCP. - tgtBlock /= int64(bc.config.GarbageCollectionPeriod) - tgtBlock *= int64(bc.config.GarbageCollectionPeriod) + tgtBlock /= int64(bc.config.Ledger.GarbageCollectionPeriod) + tgtBlock *= int64(bc.config.Ledger.GarbageCollectionPeriod) // Count periods. - oldHeight /= bc.config.GarbageCollectionPeriod - newHeight /= bc.config.GarbageCollectionPeriod - if tgtBlock > int64(bc.config.GarbageCollectionPeriod) && newHeight != oldHeight { - tgtBlock /= int64(bc.config.GarbageCollectionPeriod) - tgtBlock *= int64(bc.config.GarbageCollectionPeriod) + oldHeight /= bc.config.Ledger.GarbageCollectionPeriod + newHeight /= bc.config.Ledger.GarbageCollectionPeriod + if tgtBlock > int64(bc.config.Ledger.GarbageCollectionPeriod) && newHeight != oldHeight { + tgtBlock /= int64(bc.config.Ledger.GarbageCollectionPeriod) + tgtBlock *= int64(bc.config.Ledger.GarbageCollectionPeriod) dur = bc.stateRoot.GC(uint32(tgtBlock), bc.store) dur += bc.removeOldTransfers(uint32(tgtBlock)) } @@ -1298,12 +1309,12 @@ func (bc *Blockchain) AddBlock(block *block.Block) error { } if block.Index == bc.HeaderHeight()+1 { - err := bc.addHeaders(bc.config.VerifyBlocks, &block.Header) + err := bc.addHeaders(bc.config.Ledger.VerifyBlocks, &block.Header) if err != nil { return err } } - if bc.config.VerifyBlocks { + if bc.config.Ledger.VerifyBlocks { merkle := block.ComputeMerkleRoot() if !block.MerkleRoot.Equals(merkle) { return errors.New("invalid block: MerkleRoot mismatch") @@ -1333,7 +1344,7 @@ func (bc *Blockchain) AddBlock(block *block.Block) error { // AddHeaders processes the given headers and add them to the // HeaderHashList. It expects headers to be sorted by index. func (bc *Blockchain) AddHeaders(headers ...*block.Header) error { - return bc.addHeaders(bc.config.VerifyBlocks, headers...) + return bc.addHeaders(bc.config.Ledger.VerifyBlocks, headers...) } // addHeaders is an internal implementation of AddHeaders (`verify` parameter @@ -1415,7 +1426,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error transCache = make(map[util.Uint160]transferData) ) kvcache.StoreAsCurrentBlock(block) - if bc.config.RemoveUntraceableBlocks { + if bc.config.Ledger.RemoveUntraceableBlocks { var start, stop uint32 if bc.config.P2PStateExchangeExtensions { // remove batch of old blocks starting from P2-MaxTraceableBlocks-StateSyncInterval up to P2-MaxTraceableBlocks @@ -1567,7 +1578,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error } } - if bc.config.SaveStorageBatch { + if bc.config.Ledger.SaveStorageBatch { bc.lastBatch = cache.GetBatch() } // Every persist cycle we also compact our in-memory MPT. It's flushed @@ -1878,7 +1889,7 @@ func (bc *Blockchain) GetTokenLastUpdated(acc util.Uint160) (map[int32]uint32, e if err != nil { return nil, err } - if bc.config.P2PStateExchangeExtensions && bc.config.RemoveUntraceableBlocks { + if bc.config.P2PStateExchangeExtensions && bc.config.Ledger.RemoveUntraceableBlocks { if _, ok := info.LastUpdated[bc.contracts.NEO.ID]; !ok { nBalance, lub := bc.contracts.NEO.BalanceOf(bc.dao, acc) if nBalance.Sign() != 0 { @@ -2121,7 +2132,7 @@ func (bc *Blockchain) GetNatives() []state.NativeContract { } // GetConfig returns the config stored in the blockchain. -func (bc *Blockchain) GetConfig() config.ProtocolConfiguration { +func (bc *Blockchain) GetConfig() config.Blockchain { return bc.config } @@ -2584,7 +2595,7 @@ func (bc *Blockchain) GetTestVM(t trigger.Type, tx *transaction.Transaction, b * // GetTestHistoricVM returns an interop context with VM set up for a test run. func (bc *Blockchain) GetTestHistoricVM(t trigger.Type, tx *transaction.Transaction, nextBlockHeight uint32) (*interop.Context, error) { - if bc.config.KeepOnlyLatestState { + if bc.config.Ledger.KeepOnlyLatestState { return nil, errors.New("only latest state is supported") } b, err := bc.getFakeNextBlock(nextBlockHeight) @@ -2592,7 +2603,7 @@ func (bc *Blockchain) GetTestHistoricVM(t trigger.Type, tx *transaction.Transact return nil, fmt.Errorf("failed to create fake block for height %d: %w", nextBlockHeight, err) } var mode = mpt.ModeAll - if bc.config.RemoveUntraceableBlocks { + if bc.config.Ledger.RemoveUntraceableBlocks { if b.Index < bc.BlockHeight()-bc.config.MaxTraceableBlocks { return nil, fmt.Errorf("state for height %d is outdated and removed from the storage", b.Index) } diff --git a/pkg/core/blockchain_core_test.go b/pkg/core/blockchain_core_test.go index 529d12f49..eadb0b183 100644 --- a/pkg/core/blockchain_core_test.go +++ b/pkg/core/blockchain_core_test.go @@ -32,21 +32,21 @@ func TestVerifyHeader(t *testing.T) { t.Run("Hash", func(t *testing.T) { h := prev.Hash() h[0] = ^h[0] - hdr := newBlock(bc.config, 1, h).Header + hdr := newBlock(bc.config.ProtocolConfiguration, 1, h).Header require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrHashMismatch)) }) t.Run("Index", func(t *testing.T) { - hdr := newBlock(bc.config, 3, prev.Hash()).Header + hdr := newBlock(bc.config.ProtocolConfiguration, 3, prev.Hash()).Header require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrIndexMismatch)) }) t.Run("Timestamp", func(t *testing.T) { - hdr := newBlock(bc.config, 1, prev.Hash()).Header + hdr := newBlock(bc.config.ProtocolConfiguration, 1, prev.Hash()).Header hdr.Timestamp = 0 require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrInvalidTimestamp)) }) }) t.Run("Valid", func(t *testing.T) { - hdr := newBlock(bc.config, 1, prev.Hash()).Header + hdr := newBlock(bc.config.ProtocolConfiguration, 1, prev.Hash()).Header require.NoError(t, bc.verifyHeader(&hdr, &prev)) }) } @@ -144,12 +144,12 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { maxTraceable uint32 = 6 ) spountCfg := func(c *config.Config) { - c.ProtocolConfiguration.RemoveUntraceableBlocks = true + c.ApplicationConfiguration.RemoveUntraceableBlocks = true c.ProtocolConfiguration.StateRootInHeader = true c.ProtocolConfiguration.P2PStateExchangeExtensions = true c.ProtocolConfiguration.StateSyncInterval = stateSyncInterval c.ProtocolConfiguration.MaxTraceableBlocks = maxTraceable - c.ProtocolConfiguration.KeepOnlyLatestState = true + c.ApplicationConfiguration.KeepOnlyLatestState = true } bcSpout := newTestChainWithCustomCfg(t, spountCfg) @@ -190,7 +190,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { require.NoError(t, err) cfg(&unitTestNetCfg) log := zaptest.NewLogger(t) - _, err = NewBlockchain(store, unitTestNetCfg.ProtocolConfiguration, log) + _, err = NewBlockchain(store, unitTestNetCfg.Blockchain(), log) if len(errText) != 0 { require.Error(t, err) require.True(t, strings.Contains(err.Error(), errText)) @@ -200,7 +200,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { } boltCfg := func(c *config.Config) { spountCfg(c) - c.ProtocolConfiguration.KeepOnlyLatestState = true + c.ApplicationConfiguration.KeepOnlyLatestState = true } // manually store statejump stage to check statejump recover process bPrefix[0] = byte(storage.SYSStateChangeStage) @@ -219,7 +219,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { bcSpout.dao.Store.Put([]byte{byte(storage.SYSStateSyncPoint)}, point) checkNewBlockchainErr(t, func(c *config.Config) { boltCfg(c) - c.ProtocolConfiguration.RemoveUntraceableBlocks = false + c.ApplicationConfiguration.RemoveUntraceableBlocks = false }, bcSpout.dao.Store, "state jump was not completed, but P2PStateExchangeExtensions are disabled or archival node capability is on") }) t.Run("invalid state sync point", func(t *testing.T) { diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go index d7b8cbfcf..cd057bdb5 100644 --- a/pkg/core/blockchain_neotest_test.go +++ b/pkg/core/blockchain_neotest_test.go @@ -62,7 +62,7 @@ func newLevelDBForTestingWithPath(t testing.TB, dbPath string) (storage.Store, s func TestBlockchain_StartFromExistingDB(t *testing.T) { ps, path := newLevelDBForTestingWithPath(t, "") - customConfig := func(c *config.ProtocolConfiguration) { + customConfig := func(c *config.Blockchain) { c.StateRootInHeader = true // Need for P2PStateExchangeExtensions check. c.P2PSigExtensions = true // Need for basic chain initializer. } @@ -106,7 +106,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { }) t.Run("mismatch StateRootInHeader", func(t *testing.T) { ps = newPS(t) - _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) { + _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) { customConfig(c) c.StateRootInHeader = false }, ps) @@ -115,7 +115,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { }) t.Run("mismatch P2PSigExtensions", func(t *testing.T) { ps = newPS(t) - _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) { + _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) { customConfig(c) c.P2PSigExtensions = false }, ps) @@ -124,7 +124,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { }) t.Run("mismatch P2PStateExchangeExtensions", func(t *testing.T) { ps = newPS(t) - _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) { + _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) { customConfig(c) c.StateRootInHeader = true c.P2PStateExchangeExtensions = true @@ -134,9 +134,9 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { }) t.Run("mismatch KeepOnlyLatestState", func(t *testing.T) { ps = newPS(t) - _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) { + _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) { customConfig(c) - c.KeepOnlyLatestState = true + c.Ledger.KeepOnlyLatestState = true }, ps) require.Error(t, err) require.True(t, strings.Contains(err.Error(), "KeepOnlyLatestState setting mismatch"), err) @@ -228,7 +228,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { */ t.Run("invalid native contract deactivation", func(t *testing.T) { ps = newPS(t) - _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) { + _, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) { customConfig(c) c.NativeUpdateHistories = map[string][]uint32{ nativenames.Policy: {0}, @@ -291,7 +291,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) { } func TestBlockchain_AddHeaders(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.StateRootInHeader = true }) e := neotest.NewExecutor(t, bc, acc, acc) @@ -342,7 +342,7 @@ func TestBlockchain_AddHeaders(t *testing.T) { } func TestBlockchain_AddBlockStateRoot(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.StateRootInHeader = true }) e := neotest.NewExecutor(t, bc, acc, acc) @@ -371,7 +371,7 @@ func TestBlockchain_AddBlockStateRoot(t *testing.T) { } func TestBlockchain_AddHeadersStateRoot(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.StateRootInHeader = true }) e := neotest.NewExecutor(t, bc, acc, acc) @@ -401,7 +401,7 @@ func TestBlockchain_AddHeadersStateRoot(t *testing.T) { } func TestBlockchain_AddBadBlock(t *testing.T) { - check := func(t *testing.T, b *block.Block, cfg func(c *config.ProtocolConfiguration)) { + check := func(t *testing.T, b *block.Block, cfg func(c *config.Blockchain)) { bc, _ := chain.NewSingleWithCustomConfig(t, cfg) err := bc.AddBlock(b) if cfg == nil { @@ -420,25 +420,25 @@ func TestBlockchain_AddBadBlock(t *testing.T) { b := e.NewUnsignedBlock(t, tx) e.SignBlock(b) check(t, b, nil) - check(t, b, func(c *config.ProtocolConfiguration) { - c.VerifyBlocks = false + check(t, b, func(c *config.Blockchain) { + c.Ledger.VerifyBlocks = false }) b = e.NewUnsignedBlock(t) b.PrevHash = util.Uint256{} // Intentionally make block invalid. e.SignBlock(b) check(t, b, nil) - check(t, b, func(c *config.ProtocolConfiguration) { - c.VerifyBlocks = false + check(t, b, func(c *config.Blockchain) { + c.Ledger.VerifyBlocks = false }) tx = e.NewUnsignedTx(t, neoHash, "transfer", acc.ScriptHash(), util.Uint160{1, 2, 3}, 1, nil) // Check the good tx. e.SignTx(t, tx, -1, acc) b = e.NewUnsignedBlock(t, tx) e.SignBlock(b) - check(t, b, func(c *config.ProtocolConfiguration) { + check(t, b, func(c *config.Blockchain) { c.VerifyTransactions = true - c.VerifyBlocks = true + c.Ledger.VerifyBlocks = true }) } @@ -584,7 +584,7 @@ func TestBlockchain_VerifyHashAgainstScript(t *testing.T) { } func TestBlockchain_IsTxStillRelevant(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, acc, acc) @@ -903,10 +903,10 @@ func TestBlockchain_RemoveUntraceable(t *testing.T) { } } t.Run("P2PStateExchangeExtensions off", func(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.MaxTraceableBlocks = 2 - c.GarbageCollectionPeriod = 2 - c.RemoveUntraceableBlocks = true + c.Ledger.GarbageCollectionPeriod = 2 + c.Ledger.RemoveUntraceableBlocks = true }) e := neotest.NewExecutor(t, bc, acc, acc) neoValidatorInvoker := e.ValidatorInvoker(e.NativeHash(t, nativenames.Neo)) @@ -934,10 +934,10 @@ func TestBlockchain_RemoveUntraceable(t *testing.T) { check(t, bc, tx1Hash, b1.Hash(), sRoot.Root, true) }) t.Run("P2PStateExchangeExtensions on", func(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.MaxTraceableBlocks = 2 - c.GarbageCollectionPeriod = 2 - c.RemoveUntraceableBlocks = true + c.Ledger.GarbageCollectionPeriod = 2 + c.Ledger.RemoveUntraceableBlocks = true c.P2PStateExchangeExtensions = true c.StateSyncInterval = 2 c.StateRootInHeader = true @@ -1047,7 +1047,7 @@ func TestConfigNativeUpdateHistory(t *testing.T) { } func TestBlockchain_VerifyTx(t *testing.T) { - bc, validator, committee := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, validator, committee := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true c.ReservedAttributes = true }) @@ -1467,7 +1467,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { return tx } t.Run("Disabled", func(t *testing.T) { - bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = false c.ReservedAttributes = false }) @@ -1509,7 +1509,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { return tx } t.Run("Disabled", func(t *testing.T) { - bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = false c.ReservedAttributes = false }) @@ -1553,7 +1553,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { return tx } t.Run("disabled", func(t *testing.T) { - bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = false c.ReservedAttributes = false }) @@ -1649,7 +1649,7 @@ func TestBlockchain_VerifyTx(t *testing.T) { return tx } t.Run("Disabled", func(t *testing.T) { - bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = false c.ReservedAttributes = false }) @@ -1909,7 +1909,7 @@ func TestBlockchain_Bug1728(t *testing.T) { func TestBlockchain_ResetStateErrors(t *testing.T) { chainHeight := 3 - checkResetErr := func(t *testing.T, cfg func(c *config.ProtocolConfiguration), h uint32, errText string) { + checkResetErr := func(t *testing.T, cfg func(c *config.Blockchain), h uint32, errText string) { db, path := newLevelDBForTestingWithPath(t, t.TempDir()) bc, validators, committee := chain.NewMultiWithCustomConfigAndStore(t, cfg, db, false) e := neotest.NewExecutor(t, bc, validators, committee) @@ -1937,13 +1937,13 @@ func TestBlockchain_ResetStateErrors(t *testing.T) { checkResetErr(t, nil, uint32(chainHeight), "") }) t.Run("KeepOnlyLatestState is enabled", func(t *testing.T) { - checkResetErr(t, func(c *config.ProtocolConfiguration) { - c.KeepOnlyLatestState = true + checkResetErr(t, func(c *config.Blockchain) { + c.Ledger.KeepOnlyLatestState = true }, uint32(chainHeight-1), "KeepOnlyLatestState is enabled") }) t.Run("some blocks where removed", func(t *testing.T) { - checkResetErr(t, func(c *config.ProtocolConfiguration) { - c.RemoveUntraceableBlocks = true + checkResetErr(t, func(c *config.Blockchain) { + c.Ledger.RemoveUntraceableBlocks = true c.MaxTraceableBlocks = 2 }, uint32(chainHeight-3), "RemoveUntraceableBlocks is enabled, a necessary batch of traceable blocks has already been removed") }) @@ -1954,7 +1954,7 @@ func TestBlockchain_ResetStateErrors(t *testing.T) { func TestBlockchain_ResetState(t *testing.T) { // Create the DB. db, path := newLevelDBForTestingWithPath(t, t.TempDir()) - bc, validators, committee := chain.NewMultiWithCustomConfigAndStore(t, func(cfg *config.ProtocolConfiguration) { + bc, validators, committee := chain.NewMultiWithCustomConfigAndStore(t, func(cfg *config.Blockchain) { cfg.P2PSigExtensions = true }, db, false) go bc.Run() @@ -2025,7 +2025,7 @@ func TestBlockchain_ResetState(t *testing.T) { // Start new chain with existing DB, but do not run it. db, _ = newLevelDBForTestingWithPath(t, path) - bc, _, _ = chain.NewMultiWithCustomConfigAndStore(t, func(cfg *config.ProtocolConfiguration) { + bc, _, _ = chain.NewMultiWithCustomConfigAndStore(t, func(cfg *config.Blockchain) { cfg.P2PSigExtensions = true }, db, false) defer db.Close() diff --git a/pkg/core/chaindump/dump.go b/pkg/core/chaindump/dump.go index 802395591..37826848f 100644 --- a/pkg/core/chaindump/dump.go +++ b/pkg/core/chaindump/dump.go @@ -13,7 +13,7 @@ import ( type DumperRestorer interface { AddBlock(block *block.Block) error GetBlock(hash util.Uint256) (*block.Block, error) - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetHeaderHash(uint32) util.Uint256 } diff --git a/pkg/core/chaindump/dump_test.go b/pkg/core/chaindump/dump_test.go index 5f5c8c49b..3ae6b3bb9 100644 --- a/pkg/core/chaindump/dump_test.go +++ b/pkg/core/chaindump/dump_test.go @@ -16,30 +16,30 @@ import ( func TestBlockchain_DumpAndRestore(t *testing.T) { t.Run("no state root", func(t *testing.T) { - testDumpAndRestore(t, func(c *config.ProtocolConfiguration) { + testDumpAndRestore(t, func(c *config.Blockchain) { c.StateRootInHeader = false c.P2PSigExtensions = true }, nil) }) t.Run("with state root", func(t *testing.T) { - testDumpAndRestore(t, func(c *config.ProtocolConfiguration) { + testDumpAndRestore(t, func(c *config.Blockchain) { c.StateRootInHeader = true c.P2PSigExtensions = true }, nil) }) t.Run("remove untraceable", func(t *testing.T) { // Dump can only be created if all blocks and transactions are present. - testDumpAndRestore(t, func(c *config.ProtocolConfiguration) { + testDumpAndRestore(t, func(c *config.Blockchain) { c.P2PSigExtensions = true - }, func(c *config.ProtocolConfiguration) { + }, func(c *config.Blockchain) { c.MaxTraceableBlocks = 2 - c.RemoveUntraceableBlocks = true + c.Ledger.RemoveUntraceableBlocks = true c.P2PSigExtensions = true }) }) } -func testDumpAndRestore(t *testing.T, dumpF, restoreF func(c *config.ProtocolConfiguration)) { +func testDumpAndRestore(t *testing.T, dumpF, restoreF func(c *config.Blockchain)) { if restoreF == nil { restoreF = dumpF } diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index fc74f3849..7e2c7b0ac 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -52,7 +52,7 @@ func initTestChainNoCheck(t testing.TB, st storage.Store, f func(*config.Config) if _, ok := t.(*testing.B); ok { log = zap.NewNop() } - return NewBlockchain(st, unitTestNetCfg.ProtocolConfiguration, log) + return NewBlockchain(st, unitTestNetCfg.Blockchain(), log) } func (bc *Blockchain) newBlock(txs ...*transaction.Transaction) *block.Block { @@ -69,9 +69,9 @@ func (bc *Blockchain) newBlock(txs ...*transaction.Transaction) *block.Block { if err != nil { panic(err) } - return newBlockWithState(bc.config, lastBlock.Index+1, lastBlock.Hash(), &sr.Root, txs...) + return newBlockWithState(bc.config.ProtocolConfiguration, lastBlock.Index+1, lastBlock.Hash(), &sr.Root, txs...) } - return newBlock(bc.config, lastBlock.Index+1, lastBlock.Hash(), txs...) + return newBlock(bc.config.ProtocolConfiguration, lastBlock.Index+1, lastBlock.Hash(), txs...) } func newBlock(cfg config.ProtocolConfiguration, index uint32, prev util.Uint256, txs ...*transaction.Transaction) *block.Block { @@ -118,7 +118,7 @@ func (bc *Blockchain) genBlocks(n int) ([]*block.Block, error) { lastHash := bc.topBlock.Load().(*block.Block).Hash() lastIndex := bc.topBlock.Load().(*block.Block).Index for i := 0; i < n; i++ { - blocks[i] = newBlock(bc.config, uint32(i)+lastIndex+1, lastHash) + blocks[i] = newBlock(bc.config.ProtocolConfiguration, uint32(i)+lastIndex+1, lastHash) if err := bc.AddBlock(blocks[i]); err != nil { return blocks, err } diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index 616ccfffd..1d1448014 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -39,7 +39,7 @@ type Ledger interface { BlockHeight() uint32 CurrentBlockHash() util.Uint256 GetBlock(hash util.Uint256) (*block.Block, error) - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetHeaderHash(uint32) util.Uint256 } @@ -75,7 +75,7 @@ func NewContext(trigger trigger.Type, bc Ledger, d *dao.Simple, baseExecFee, bas loadTokenFunc func(ic *Context, id int32) error, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context { dao := d.GetPrivate() - cfg := bc.GetConfig() + cfg := bc.GetConfig().ProtocolConfiguration return &Context{ Chain: bc, Network: uint32(cfg.Magic), diff --git a/pkg/core/interop/contract/account_test.go b/pkg/core/interop/contract/account_test.go index 84a655571..2359c185e 100644 --- a/pkg/core/interop/contract/account_test.go +++ b/pkg/core/interop/contract/account_test.go @@ -118,7 +118,7 @@ func TestCreateMultisigAccount(t *testing.T) { } func TestCreateAccount_Hardfork(t *testing.T) { - bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true // `basicchain.Init` requires Notary enabled c.Hardforks = map[string]uint32{ config.HFAspidochelone.String(): 2, diff --git a/pkg/core/native/invocation_test.go b/pkg/core/native/invocation_test.go index 519dd30da..c5a727533 100644 --- a/pkg/core/native/invocation_test.go +++ b/pkg/core/native/invocation_test.go @@ -90,7 +90,7 @@ func TestNativeContract_InvokeInternal(t *testing.T) { }) t.Run("fail, bad NativeUpdateHistory height", func(t *testing.T) { - bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.NativeUpdateHistories = map[string][]uint32{ nativenames.Policy: {0}, nativenames.Neo: {0}, diff --git a/pkg/core/native/management_neotest_test.go b/pkg/core/native/management_neotest_test.go index f805d439b..1647eccdd 100644 --- a/pkg/core/native/management_neotest_test.go +++ b/pkg/core/native/management_neotest_test.go @@ -22,7 +22,7 @@ func TestManagement_GetNEP17Contracts(t *testing.T) { }) t.Run("basic chain", func(t *testing.T) { - bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true // `basicchain.Init` requires Notary enabled }) e := neotest.NewExecutor(t, bc, validators, committee) diff --git a/pkg/core/native/native_test/gas_test.go b/pkg/core/native/native_test/gas_test.go index dd270ade2..3c08fbf30 100644 --- a/pkg/core/native/native_test/gas_test.go +++ b/pkg/core/native/native_test/gas_test.go @@ -65,7 +65,7 @@ func TestGAS_RewardWithP2PSigExtensionsEnabled(t *testing.T) { nKeys = 4 ) - bc, validator, committee := chain.NewMultiWithCustomConfig(t, func(cfg *config.ProtocolConfiguration) { + bc, validator, committee := chain.NewMultiWithCustomConfig(t, func(cfg *config.Blockchain) { cfg.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, validator, committee) diff --git a/pkg/core/native/native_test/ledger_test.go b/pkg/core/native/native_test/ledger_test.go index 1208aa298..3af6d346a 100644 --- a/pkg/core/native/native_test/ledger_test.go +++ b/pkg/core/native/native_test/ledger_test.go @@ -20,7 +20,7 @@ import ( ) func newLedgerClient(t *testing.T) *neotest.ContractInvoker { - bc, acc := chain.NewSingleWithCustomConfig(t, func(cfg *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(cfg *config.Blockchain) { cfg.MaxTraceableBlocks = 10 // reduce number of traceable blocks for Ledger tests }) e := neotest.NewExecutor(t, bc, acc, acc) diff --git a/pkg/core/native/native_test/notary_test.go b/pkg/core/native/native_test/notary_test.go index a7f020f61..85e3914fb 100644 --- a/pkg/core/native/native_test/notary_test.go +++ b/pkg/core/native/native_test/notary_test.go @@ -19,7 +19,7 @@ import ( ) func newNotaryClient(t *testing.T) *neotest.ContractInvoker { - bc, acc := chain.NewSingleWithCustomConfig(t, func(cfg *config.ProtocolConfiguration) { + bc, acc := chain.NewSingleWithCustomConfig(t, func(cfg *config.Blockchain) { cfg.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, acc, acc) diff --git a/pkg/core/stateroot/module.go b/pkg/core/stateroot/module.go index 07f58e006..34503d7eb 100644 --- a/pkg/core/stateroot/module.go +++ b/pkg/core/stateroot/module.go @@ -55,12 +55,12 @@ type ( ) // NewModule returns new instance of stateroot module. -func NewModule(cfg config.ProtocolConfiguration, verif VerifierFunc, log *zap.Logger, s *storage.MemCachedStore) *Module { +func NewModule(cfg config.Blockchain, verif VerifierFunc, log *zap.Logger, s *storage.MemCachedStore) *Module { var mode mpt.TrieMode - if cfg.KeepOnlyLatestState { + if cfg.Ledger.KeepOnlyLatestState { mode |= mpt.ModeLatest } - if cfg.RemoveUntraceableBlocks { + if cfg.Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeGC } return &Module{ diff --git a/pkg/core/statesync/module.go b/pkg/core/statesync/module.go index 58ce4c0cb..a611adc14 100644 --- a/pkg/core/statesync/module.go +++ b/pkg/core/statesync/module.go @@ -64,7 +64,7 @@ const ( type Ledger interface { AddHeaders(...*block.Header) error BlockHeight() uint32 - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetHeader(hash util.Uint256) (*block.Header, error) GetHeaderHash(uint32) util.Uint256 HeaderHeight() uint32 @@ -97,7 +97,7 @@ type Module struct { // NewModule returns new instance of statesync module. func NewModule(bc Ledger, stateMod *stateroot.Module, log *zap.Logger, s *dao.Simple, jumpCallback func(p uint32) error) *Module { - if !(bc.GetConfig().P2PStateExchangeExtensions && bc.GetConfig().RemoveUntraceableBlocks) { + if !(bc.GetConfig().P2PStateExchangeExtensions && bc.GetConfig().Ledger.RemoveUntraceableBlocks) { return &Module{ dao: s, bc: bc, @@ -220,7 +220,7 @@ func (s *Module) defineSyncStage() error { } var mode mpt.TrieMode // No need to enable GC here, it only has latest things. - if s.bc.GetConfig().KeepOnlyLatestState || s.bc.GetConfig().RemoveUntraceableBlocks { + if s.bc.GetConfig().Ledger.KeepOnlyLatestState || s.bc.GetConfig().Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeLatest } s.billet = mpt.NewBillet(header.PrevStateRoot, mode, @@ -323,7 +323,7 @@ func (s *Module) AddBlock(block *block.Block) error { if s.bc.GetConfig().StateRootInHeader != block.StateRootEnabled { return fmt.Errorf("stateroot setting mismatch: %v != %v", s.bc.GetConfig().StateRootInHeader, block.StateRootEnabled) } - if s.bc.GetConfig().VerifyBlocks { + if s.bc.GetConfig().Ledger.VerifyBlocks { merkle := block.ComputeMerkleRoot() if !block.MerkleRoot.Equals(merkle) { return errors.New("invalid block: MerkleRoot mismatch") @@ -492,7 +492,7 @@ func (s *Module) Traverse(root util.Uint256, process func(node mpt.Node, nodeByt var mode mpt.TrieMode // GC must be turned off here to allow access to the archived nodes. - if s.bc.GetConfig().KeepOnlyLatestState || s.bc.GetConfig().RemoveUntraceableBlocks { + if s.bc.GetConfig().Ledger.KeepOnlyLatestState || s.bc.GetConfig().Ledger.RemoveUntraceableBlocks { mode |= mpt.ModeLatest } b := mpt.NewBillet(root, mode, 0, storage.NewMemCachedStore(s.dao.Store)) diff --git a/pkg/core/statesync/neotest_test.go b/pkg/core/statesync/neotest_test.go index 31a7a3589..f867f4ab0 100644 --- a/pkg/core/statesync/neotest_test.go +++ b/pkg/core/statesync/neotest_test.go @@ -20,7 +20,7 @@ func TestStateSyncModule_Init(t *testing.T) { stateSyncInterval = 2 maxTraceable = 3 ) - spoutCfg := func(c *config.ProtocolConfiguration) { + spoutCfg := func(c *config.Blockchain) { c.StateRootInHeader = true c.P2PStateExchangeExtensions = true c.StateSyncInterval = stateSyncInterval @@ -32,15 +32,15 @@ func TestStateSyncModule_Init(t *testing.T) { e.AddNewBlock(t) } - boltCfg := func(c *config.ProtocolConfiguration) { + boltCfg := func(c *config.Blockchain) { spoutCfg(c) - c.KeepOnlyLatestState = true - c.RemoveUntraceableBlocks = true + c.Ledger.KeepOnlyLatestState = true + c.Ledger.RemoveUntraceableBlocks = true } t.Run("error: module disabled by config", func(t *testing.T) { - bcBolt, _, _ := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bcBolt, _, _ := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { boltCfg(c) - c.RemoveUntraceableBlocks = false + c.Ledger.RemoveUntraceableBlocks = false }) module := bcBolt.GetStateSyncModule() require.Error(t, module.Init(bcSpout.BlockHeight())) // module inactive (non-archival node) @@ -288,9 +288,9 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) { maxTraceable = 6 stateSyncPoint = 24 ) - spoutCfg := func(c *config.ProtocolConfiguration) { - c.KeepOnlyLatestState = spoutEnableGC - c.RemoveUntraceableBlocks = spoutEnableGC + spoutCfg := func(c *config.Blockchain) { + c.Ledger.KeepOnlyLatestState = spoutEnableGC + c.Ledger.RemoveUntraceableBlocks = spoutEnableGC c.StateRootInHeader = true c.P2PStateExchangeExtensions = true c.StateSyncInterval = stateSyncInterval @@ -309,10 +309,10 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) { e.AddNewBlock(t) require.Equal(t, stateSyncPoint+2, int(bcSpout.BlockHeight())) - boltCfg := func(c *config.ProtocolConfiguration) { + boltCfg := func(c *config.Blockchain) { spoutCfg(c) - c.KeepOnlyLatestState = true - c.RemoveUntraceableBlocks = true + c.Ledger.KeepOnlyLatestState = true + c.Ledger.RemoveUntraceableBlocks = true } bcBoltStore := storage.NewMemoryStore() bcBolt, _, _ := chain.NewMultiWithCustomConfigAndStore(t, boltCfg, bcBoltStore, false) diff --git a/pkg/neotest/chain/chain.go b/pkg/neotest/chain/chain.go index 13a7fa174..b598c91c9 100644 --- a/pkg/neotest/chain/chain.go +++ b/pkg/neotest/chain/chain.go @@ -128,7 +128,7 @@ func NewSingle(t testing.TB) (*core.Blockchain, neotest.Signer) { // NewSingleWithCustomConfig is similar to NewSingle, but allows to override the // default configuration. -func NewSingleWithCustomConfig(t testing.TB, f func(*config.ProtocolConfiguration)) (*core.Blockchain, neotest.Signer) { +func NewSingleWithCustomConfig(t testing.TB, f func(*config.Blockchain)) (*core.Blockchain, neotest.Signer) { return NewSingleWithCustomConfigAndStore(t, f, nil, true) } @@ -137,24 +137,29 @@ func NewSingleWithCustomConfig(t testing.TB, f func(*config.ProtocolConfiguratio // Run method is called on the Blockchain instance. If not, it is its caller's // responsibility to do that before using the chain and // to properly Close the chain when done. -func NewSingleWithCustomConfigAndStore(t testing.TB, f func(cfg *config.ProtocolConfiguration), st storage.Store, run bool) (*core.Blockchain, neotest.Signer) { - protoCfg := config.ProtocolConfiguration{ - Magic: netmode.UnitTestNet, - MaxTraceableBlocks: MaxTraceableBlocks, - TimePerBlock: TimePerBlock, - StandbyCommittee: []string{hex.EncodeToString(committeeAcc.PublicKey().Bytes())}, - ValidatorsCount: 1, - VerifyBlocks: true, - VerifyTransactions: true, +func NewSingleWithCustomConfigAndStore(t testing.TB, f func(cfg *config.Blockchain), st storage.Store, run bool) (*core.Blockchain, neotest.Signer) { + var cfg = config.Blockchain{ + ProtocolConfiguration: config.ProtocolConfiguration{ + Magic: netmode.UnitTestNet, + MaxTraceableBlocks: MaxTraceableBlocks, + TimePerBlock: TimePerBlock, + StandbyCommittee: []string{hex.EncodeToString(committeeAcc.PublicKey().Bytes())}, + ValidatorsCount: 1, + VerifyTransactions: true, + }, + Ledger: config.Ledger{ + VerifyBlocks: true, + }, } + if f != nil { - f(&protoCfg) + f(&cfg) } if st == nil { st = storage.NewMemoryStore() } log := zaptest.NewLogger(t) - bc, err := core.NewBlockchain(st, protoCfg, log) + bc, err := core.NewBlockchain(st, cfg, log) require.NoError(t, err) if run { go bc.Run() @@ -172,7 +177,7 @@ func NewMulti(t testing.TB) (*core.Blockchain, neotest.Signer, neotest.Signer) { // NewMultiWithCustomConfig is similar to NewMulti, except it allows to override the // default configuration. -func NewMultiWithCustomConfig(t testing.TB, f func(*config.ProtocolConfiguration)) (*core.Blockchain, neotest.Signer, neotest.Signer) { +func NewMultiWithCustomConfig(t testing.TB, f func(*config.Blockchain)) (*core.Blockchain, neotest.Signer, neotest.Signer) { return NewMultiWithCustomConfigAndStore(t, f, nil, true) } @@ -181,7 +186,7 @@ func NewMultiWithCustomConfig(t testing.TB, f func(*config.ProtocolConfiguration // Run method is called on the Blockchain instance. If not, it is its caller's // responsibility to do that before using the chain and // to properly Close the chain when done. -func NewMultiWithCustomConfigAndStore(t testing.TB, f func(*config.ProtocolConfiguration), st storage.Store, run bool) (*core.Blockchain, neotest.Signer, neotest.Signer) { +func NewMultiWithCustomConfigAndStore(t testing.TB, f func(*config.Blockchain), st storage.Store, run bool) (*core.Blockchain, neotest.Signer, neotest.Signer) { bc, validator, committee, err := NewMultiWithCustomConfigAndStoreNoCheck(t, f, st) require.NoError(t, err) if run { @@ -193,24 +198,28 @@ func NewMultiWithCustomConfigAndStore(t testing.TB, f func(*config.ProtocolConfi // NewMultiWithCustomConfigAndStoreNoCheck is similar to NewMultiWithCustomConfig, // but do not perform Blockchain run and do not check Blockchain constructor error. -func NewMultiWithCustomConfigAndStoreNoCheck(t testing.TB, f func(*config.ProtocolConfiguration), st storage.Store) (*core.Blockchain, neotest.Signer, neotest.Signer, error) { - protoCfg := config.ProtocolConfiguration{ - Magic: netmode.UnitTestNet, - MaxTraceableBlocks: MaxTraceableBlocks, - TimePerBlock: TimePerBlock, - StandbyCommittee: standByCommittee, - ValidatorsCount: 4, - VerifyBlocks: true, - VerifyTransactions: true, +func NewMultiWithCustomConfigAndStoreNoCheck(t testing.TB, f func(*config.Blockchain), st storage.Store) (*core.Blockchain, neotest.Signer, neotest.Signer, error) { + var cfg = config.Blockchain{ + ProtocolConfiguration: config.ProtocolConfiguration{ + Magic: netmode.UnitTestNet, + MaxTraceableBlocks: MaxTraceableBlocks, + TimePerBlock: TimePerBlock, + StandbyCommittee: standByCommittee, + ValidatorsCount: 4, + VerifyTransactions: true, + }, + Ledger: config.Ledger{ + VerifyBlocks: true, + }, } if f != nil { - f(&protoCfg) + f(&cfg) } if st == nil { st = storage.NewMemoryStore() } log := zaptest.NewLogger(t) - bc, err := core.NewBlockchain(st, protoCfg, log) + bc, err := core.NewBlockchain(st, cfg, log) return bc, neotest.NewMultiSigner(multiValidatorAcc...), neotest.NewMultiSigner(multiCommitteeAcc...), err } diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 959e07cb9..6aeed020e 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -207,7 +207,7 @@ func newTestServer(t *testing.T, serverConfig ServerConfig) *Server { return newTestServerWithCustomCfg(t, serverConfig, nil) } -func newTestServerWithCustomCfg(t *testing.T, serverConfig ServerConfig, protocolCfg func(*config.ProtocolConfiguration)) *Server { +func newTestServerWithCustomCfg(t *testing.T, serverConfig ServerConfig, protocolCfg func(*config.Blockchain)) *Server { if len(serverConfig.Addresses) == 0 { // Normally it will be done by ApplicationConfiguration.GetAddresses(). serverConfig.Addresses = []config.AnnounceableAddress{{Address: ":0"}} diff --git a/pkg/network/server.go b/pkg/network/server.go index 1e248fa37..d0f0c6e87 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -59,7 +59,7 @@ type ( mempool.Feer Blockqueuer GetBlock(hash util.Uint256) (*block.Block, error) - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetHeader(hash util.Uint256) (*block.Header, error) GetHeaderHash(uint32) util.Uint256 GetMaxVerificationGAS() int64 @@ -177,7 +177,7 @@ func newServerFromConstructors(config ServerConfig, chain Ledger, stSync StateSy ServerConfig: config, chain: chain, id: randomID(), - config: chain.GetConfig(), + config: chain.GetConfig().ProtocolConfiguration, quit: make(chan struct{}), relayFin: make(chan struct{}), register: make(chan Peer), diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index 175a32ca9..edd1968b1 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -56,10 +56,11 @@ func (f *fakeConsensus) OnTransaction(tx *transaction.Transaction) { func (f *fakeConsensus) GetPayload(h util.Uint256) *payload.Extensible { panic("implement me") } func TestNewServer(t *testing.T) { - bc := &fakechain.FakeChain{ProtocolConfiguration: config.ProtocolConfiguration{ - P2PStateExchangeExtensions: true, - StateRootInHeader: true, - }} + bc := &fakechain.FakeChain{Blockchain: config.Blockchain{ + ProtocolConfiguration: config.ProtocolConfiguration{ + P2PStateExchangeExtensions: true, + StateRootInHeader: true, + }}} s, err := newServerFromConstructors(ServerConfig{}, bc, new(fakechain.FakeStateSync), nil, newFakeTransp, newTestDiscovery) require.Error(t, err) @@ -387,7 +388,7 @@ func (s *Server) testHandleMessage(t *testing.T, p Peer, cmd CommandType, pl pay return s } -func startTestServer(t *testing.T, protocolCfg ...func(*config.ProtocolConfiguration)) *Server { +func startTestServer(t *testing.T, protocolCfg ...func(*config.Blockchain)) *Server { var s *Server srvCfg := ServerConfig{UserAgent: "/test/"} if protocolCfg != nil { @@ -820,15 +821,15 @@ func TestHandleGetMPTData(t *testing.T) { require.Eventually(t, recvResponse.Load, time.Second, time.Millisecond) } t.Run("KeepOnlyLatestState on", func(t *testing.T) { - s := startTestServer(t, func(c *config.ProtocolConfiguration) { + s := startTestServer(t, func(c *config.Blockchain) { c.P2PStateExchangeExtensions = true - c.KeepOnlyLatestState = true + c.Ledger.KeepOnlyLatestState = true }) check(t, s) }) t.Run("good", func(t *testing.T) { - s := startTestServer(t, func(c *config.ProtocolConfiguration) { + s := startTestServer(t, func(c *config.Blockchain) { c.P2PStateExchangeExtensions = true }) check(t, s) diff --git a/pkg/services/notary/core_test.go b/pkg/services/notary/core_test.go index fe1c9e156..c383c39be 100644 --- a/pkg/services/notary/core_test.go +++ b/pkg/services/notary/core_test.go @@ -70,7 +70,7 @@ func dupNotaryRequest(t *testing.T, p *payload.P2PNotaryRequest) *payload.P2PNot } func TestNotary(t *testing.T) { - bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, validators, committee) diff --git a/pkg/services/oracle/oracle.go b/pkg/services/oracle/oracle.go index 78322a4ba..d1212aff7 100644 --- a/pkg/services/oracle/oracle.go +++ b/pkg/services/oracle/oracle.go @@ -27,7 +27,7 @@ type ( BlockHeight() uint32 FeePerByte() int64 GetBaseExecFee() int64 - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetMaxVerificationGAS() int64 GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) (*interop.Context, error) GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) diff --git a/pkg/services/rpcsrv/server.go b/pkg/services/rpcsrv/server.go index ce1e7f847..eb72ccd09 100644 --- a/pkg/services/rpcsrv/server.go +++ b/pkg/services/rpcsrv/server.go @@ -72,7 +72,7 @@ type ( GetBaseExecFee() int64 GetBlock(hash util.Uint256) (*block.Block, error) GetCommittee() (keys.PublicKeys, error) - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain GetContractScriptHash(id int32) (util.Uint160, error) GetContractState(hash util.Uint160) *state.Contract GetEnrollments() ([]state.Validator, error) @@ -274,7 +274,7 @@ func New(chain Ledger, conf config.RPC, coreServer *network.Server, } } - protoCfg := chain.GetConfig() + protoCfg := chain.GetConfig().ProtocolConfiguration if conf.SessionEnabled { if conf.SessionExpirationTime <= 0 { conf.SessionExpirationTime = int(protoCfg.TimePerBlock / time.Second) @@ -935,7 +935,7 @@ contract_loop: lub, ok := lastUpdated[cs.ID] if !ok { cfg := s.chain.GetConfig() - if !cfg.P2PStateExchangeExtensions && cfg.RemoveUntraceableBlocks { + if !cfg.P2PStateExchangeExtensions && cfg.Ledger.RemoveUntraceableBlocks { return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get LastUpdatedBlock for balance of %s token: internal database inconsistency", cs.Hash.StringLE())) } lub = stateSyncPoint @@ -1057,7 +1057,7 @@ func (s *Server) getNEP17Balances(ps params.Params) (interface{}, *neorpc.Error) lub, ok := lastUpdated[cs.ID] if !ok { cfg := s.chain.GetConfig() - if !cfg.P2PStateExchangeExtensions && cfg.RemoveUntraceableBlocks { + if !cfg.P2PStateExchangeExtensions && cfg.Ledger.RemoveUntraceableBlocks { return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get LastUpdatedBlock for balance of %s token: internal database inconsistency", cs.Hash.StringLE())) } lub = stateSyncPoint @@ -1396,7 +1396,7 @@ func makeStorageKey(id int32, key []byte) []byte { var errKeepOnlyLatestState = errors.New("'KeepOnlyLatestState' setting is enabled") func (s *Server) getProof(ps params.Params) (interface{}, *neorpc.Error) { - if s.chain.GetConfig().KeepOnlyLatestState { + if s.chain.GetConfig().Ledger.KeepOnlyLatestState { return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'getproof' is not supported: %s", errKeepOnlyLatestState)) } root, err := ps.Value(0).GetUint256() @@ -1427,7 +1427,7 @@ func (s *Server) getProof(ps params.Params) (interface{}, *neorpc.Error) { } func (s *Server) verifyProof(ps params.Params) (interface{}, *neorpc.Error) { - if s.chain.GetConfig().KeepOnlyLatestState { + if s.chain.GetConfig().Ledger.KeepOnlyLatestState { return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'verifyproof' is not supported: %s", errKeepOnlyLatestState)) } root, err := ps.Value(0).GetUint256() @@ -1455,7 +1455,7 @@ func (s *Server) getState(ps params.Params) (interface{}, *neorpc.Error) { if err != nil { return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot") } - if s.chain.GetConfig().KeepOnlyLatestState { + if s.chain.GetConfig().Ledger.KeepOnlyLatestState { curr, err := s.chain.GetStateModule().GetStateRoot(s.chain.BlockHeight()) if err != nil { return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err)) @@ -1489,7 +1489,7 @@ func (s *Server) findStates(ps params.Params) (interface{}, *neorpc.Error) { if err != nil { return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot") } - if s.chain.GetConfig().KeepOnlyLatestState { + if s.chain.GetConfig().Ledger.KeepOnlyLatestState { curr, err := s.chain.GetStateModule().GetStateRoot(s.chain.BlockHeight()) if err != nil { return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err)) @@ -2041,7 +2041,7 @@ func (s *Server) getInvokeContractVerifyParams(reqParams params.Params) (util.Ui // specified stateroot is stored at the specified height for further request // handling consistency. func (s *Server) getHistoricParams(reqParams params.Params) (uint32, *neorpc.Error) { - if s.chain.GetConfig().KeepOnlyLatestState { + if s.chain.GetConfig().Ledger.KeepOnlyLatestState { return 0, neorpc.NewInvalidRequestError(fmt.Sprintf("only latest state is supported: %s", errKeepOnlyLatestState)) } if len(reqParams) < 1 { diff --git a/pkg/services/rpcsrv/server_helper_test.go b/pkg/services/rpcsrv/server_helper_test.go index 72be966d8..eb11f75d7 100644 --- a/pkg/services/rpcsrv/server_helper_test.go +++ b/pkg/services/rpcsrv/server_helper_test.go @@ -67,7 +67,7 @@ func getUnitTestChainWithCustomConfig(t testing.TB, enableOracle bool, enableNot memoryStore := storage.NewMemoryStore() logger := zaptest.NewLogger(t) - chain, err := core.NewBlockchain(memoryStore, cfg.ProtocolConfiguration, logger) + chain, err := core.NewBlockchain(memoryStore, cfg.Blockchain(), logger) require.NoError(t, err, "could not create chain") var orc *oracle.Oracle diff --git a/pkg/services/stateroot/service.go b/pkg/services/stateroot/service.go index 4bfd05206..4dd21e42b 100644 --- a/pkg/services/stateroot/service.go +++ b/pkg/services/stateroot/service.go @@ -21,7 +21,7 @@ import ( type ( // Ledger is an interface to Blockchain sufficient for Service. Ledger interface { - GetConfig() config.ProtocolConfiguration + GetConfig() config.Blockchain HeaderHeight() uint32 SubscribeForBlocks(ch chan *block.Block) UnsubscribeFromBlocks(ch chan *block.Block) diff --git a/pkg/services/stateroot/service_test.go b/pkg/services/stateroot/service_test.go index 92df60ad6..d71c2f101 100644 --- a/pkg/services/stateroot/service_test.go +++ b/pkg/services/stateroot/service_test.go @@ -298,7 +298,7 @@ func checkVoteBroadcasted(t *testing.T, bc *core.Blockchain, p *payload.Extensib } func TestStateroot_GetLatestStateHeight(t *testing.T) { - bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.ProtocolConfiguration) { + bc, validators, committee := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) { c.P2PSigExtensions = true }) e := neotest.NewExecutor(t, bc, validators, committee) diff --git a/scripts/gendump/main.go b/scripts/gendump/main.go index 4e7a0d309..6921ca2b7 100644 --- a/scripts/gendump/main.go +++ b/scripts/gendump/main.go @@ -132,14 +132,14 @@ func newChain() (*core.Blockchain, error) { if err != nil { return nil, err } - unitTestNetCfg.ProtocolConfiguration.VerifyBlocks = false + unitTestNetCfg.ApplicationConfiguration.VerifyBlocks = false zapCfg := zap.NewDevelopmentConfig() zapCfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel) log, err := zapCfg.Build() if err != nil { return nil, err } - chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.ProtocolConfiguration, log) + chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.Blockchain(), log) if err != nil { return nil, err }