forked from TrueCloudLab/neoneo-go
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.
This commit is contained in:
parent
199a6de737
commit
7589733017
42 changed files with 287 additions and 202 deletions
10
ROADMAP.md
10
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
|
Removal of this compatibility code is scheduled for May-June 2023 (~0.103.0
|
||||||
release).
|
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).
|
||||||
|
|
|
@ -235,7 +235,7 @@ func restoreDB(ctx *cli.Context) error {
|
||||||
|
|
||||||
dumpDir := ctx.String("dump")
|
dumpDir := ctx.String("dump")
|
||||||
if dumpDir != "" {
|
if dumpDir != "" {
|
||||||
cfg.ProtocolConfiguration.SaveStorageBatch = true
|
cfg.ApplicationConfiguration.SaveStorageBatch = true
|
||||||
}
|
}
|
||||||
|
|
||||||
chain, prometheus, pprof, err := initBCWithMetrics(cfg, log)
|
chain, prometheus, pprof, err := initBCWithMetrics(cfg, log)
|
||||||
|
@ -384,7 +384,7 @@ func mkConsensus(config config.Consensus, tpb time.Duration, chain *core.Blockch
|
||||||
Logger: log,
|
Logger: log,
|
||||||
Broadcast: serv.BroadcastExtensible,
|
Broadcast: serv.BroadcastExtensible,
|
||||||
Chain: chain,
|
Chain: chain,
|
||||||
ProtocolConfiguration: chain.GetConfig(),
|
ProtocolConfiguration: chain.GetConfig().ProtocolConfiguration,
|
||||||
RequestTx: serv.RequestTx,
|
RequestTx: serv.RequestTx,
|
||||||
StopTxFlow: serv.StopTxFlow,
|
StopTxFlow: serv.StopTxFlow,
|
||||||
Wallet: config.UnlockWallet,
|
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)
|
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 {
|
if err != nil {
|
||||||
errText := "could not initialize blockchain: %w"
|
errText := "could not initialize blockchain: %w"
|
||||||
errArgs := []interface{}{err}
|
errArgs := []interface{}{err}
|
||||||
|
|
|
@ -468,7 +468,7 @@ func NewWithConfig(printLogotype bool, onExit func(int), c *readline.Config, cfg
|
||||||
onExit(i)
|
onExit(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
chain, err := core.NewBlockchain(store, cfg.ProtocolConfiguration, fLog)
|
chain, err := core.NewBlockchain(store, cfg.Blockchain(), fLog)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1)
|
return nil, cli.NewExitError(fmt.Errorf("could not initialize blockchain: %w", err), 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ func newTestVMClIWithState(t *testing.T) *executor {
|
||||||
}
|
}
|
||||||
store, err := storage.NewLevelDBStore(opts)
|
store, err := storage.NewLevelDBStore(opts)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
customConfig := func(c *config.ProtocolConfiguration) {
|
customConfig := func(c *config.Blockchain) {
|
||||||
c.StateRootInHeader = true // Need for P2PStateExchangeExtensions check.
|
c.StateRootInHeader = true // Need for P2PStateExchangeExtensions check.
|
||||||
c.P2PSigExtensions = true // Need for basic chain initializer.
|
c.P2PSigExtensions = true // Need for basic chain initializer.
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. |
|
| 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. |
|
| 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"). |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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
|
### P2P Configuration
|
||||||
|
|
||||||
|
@ -335,9 +340,9 @@ protocol-related settings described in the table below.
|
||||||
| Section | Type | Default value | Description | Notes |
|
| 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. |
|
| 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:<br>• `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. |
|
| 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:<br>• `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. |
|
| Magic | `uint32` | `0` | Magic number which uniquely identifies Neo network. |
|
||||||
| MaxBlockSize | `uint32` | `262144` | Maximum block size in bytes. |
|
| MaxBlockSize | `uint32` | `262144` | Maximum block size in bytes. |
|
||||||
| MaxBlockSystemFee | `int64` | `900000000000` | Maximum overall transactions system fee per block. |
|
| 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.<br>This option is valid only if `P2PSigExtensions` are enabled. | Not supported by the C# node, thus may affect heterogeneous networks functionality. |
|
| 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.<br>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:<br>• Transaction attributes `NotValidBefore`, `Conflicts` and `NotaryAssisted`<br>• Network payload of the `P2PNotaryRequest` type<br>• Native `Notary` contract<br>• Notary node module | Not supported by the C# node, thus may affect heterogeneous networks functionality. |
|
| P2PSigExtensions | `bool` | `false` | Enables following additional Notary service related logic:<br>• Transaction attributes `NotValidBefore`, `Conflicts` and `NotaryAssisted`<br>• Network payload of the `P2PNotaryRequest` type<br>• Native `Notary` contract<br>• 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: <br>• `StateSyncInterval` protocol setting <br>• 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`). |
|
| P2PStateExchangeExtensions | `bool` | `false` | Enables the following P2P MPT state data exchange logic: <br>• `StateSyncInterval` protocol setting <br>• 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. |
|
| 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. |
|
| 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. |
|
| SeedList | `[]string` | [] | List of initial nodes addresses used to establish connectivity. |
|
||||||
| StandbyCommittee | `[]string` | [] | List of public keys of standby committee validators are chosen from. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| 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. |
|
| VerifyTransactions | `bool` | `false` | Denotes whether to verify transactions in the received blocks. |
|
||||||
|
|
|
@ -65,7 +65,7 @@ func generateOracleContract(t *testing.T, saveState bool) {
|
||||||
// native hashes and saves the generated NEF and manifest to `management_contract` folder.
|
// 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.
|
// Set `saveState` flag to true and run the test to rewrite NEF and manifest files.
|
||||||
func generateManagementHelperContracts(t *testing.T, saveState bool) {
|
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
|
c.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, validator, committee)
|
e := neotest.NewExecutor(t, bc, validator, committee)
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
|
|
||||||
// FakeChain implements the Blockchainer interface, but does not provide real functionality.
|
// FakeChain implements the Blockchainer interface, but does not provide real functionality.
|
||||||
type FakeChain struct {
|
type FakeChain struct {
|
||||||
config.ProtocolConfiguration
|
config.Blockchain
|
||||||
*mempool.Pool
|
*mempool.Pool
|
||||||
blocksCh []chan *block.Block
|
blocksCh []chan *block.Block
|
||||||
Blockheight uint32
|
Blockheight uint32
|
||||||
|
@ -56,19 +56,19 @@ func NewFakeChain() *FakeChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFakeChainWithCustomCfg returns a new FakeChain structure with the specified protocol configuration.
|
// NewFakeChainWithCustomCfg returns a new FakeChain structure with the specified protocol configuration.
|
||||||
func NewFakeChainWithCustomCfg(protocolCfg func(c *config.ProtocolConfiguration)) *FakeChain {
|
func NewFakeChainWithCustomCfg(protocolCfg func(c *config.Blockchain)) *FakeChain {
|
||||||
cfg := config.ProtocolConfiguration{Magic: netmode.UnitTestNet, P2PNotaryRequestPayloadPoolSize: 10}
|
cfg := config.Blockchain{ProtocolConfiguration: config.ProtocolConfiguration{Magic: netmode.UnitTestNet, P2PNotaryRequestPayloadPoolSize: 10}}
|
||||||
if protocolCfg != nil {
|
if protocolCfg != nil {
|
||||||
protocolCfg(&cfg)
|
protocolCfg(&cfg)
|
||||||
}
|
}
|
||||||
return &FakeChain{
|
return &FakeChain{
|
||||||
Pool: mempool.New(10, 0, false),
|
Pool: mempool.New(10, 0, false),
|
||||||
PoolTxF: func(*transaction.Transaction) error { return nil },
|
PoolTxF: func(*transaction.Transaction) error { return nil },
|
||||||
poolTxWithData: func(*transaction.Transaction, interface{}, *mempool.Pool) error { return nil },
|
poolTxWithData: func(*transaction.Transaction, interface{}, *mempool.Pool) error { return nil },
|
||||||
blocks: make(map[util.Uint256]*block.Block),
|
blocks: make(map[util.Uint256]*block.Block),
|
||||||
hdrHashes: make(map[uint32]util.Uint256),
|
hdrHashes: make(map[uint32]util.Uint256),
|
||||||
txs: make(map[util.Uint256]*transaction.Transaction),
|
txs: make(map[util.Uint256]*transaction.Transaction),
|
||||||
ProtocolConfiguration: cfg,
|
Blockchain: cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,8 +159,8 @@ func (chain *FakeChain) RegisterPostBlock(f func(func(*transaction.Transaction,
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig implements the Blockchainer interface.
|
// GetConfig implements the Blockchainer interface.
|
||||||
func (chain *FakeChain) GetConfig() config.ProtocolConfiguration {
|
func (chain *FakeChain) GetConfig() config.Blockchain {
|
||||||
return chain.ProtocolConfiguration
|
return chain.Blockchain
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalculateClaimable implements the Blockchainer interface.
|
// CalculateClaimable implements the Blockchainer interface.
|
||||||
|
|
|
@ -139,7 +139,7 @@ func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch
|
||||||
|
|
||||||
memoryStore := storage.NewMemoryStore()
|
memoryStore := storage.NewMemoryStore()
|
||||||
logger := zaptest.NewLogger(t)
|
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")
|
require.NoError(t, err, "could not create chain")
|
||||||
|
|
||||||
if run {
|
if run {
|
||||||
|
@ -155,7 +155,7 @@ func NewTestChain(t *testing.T, f func(*config.Config), run bool) (*core.Blockch
|
||||||
Logger: zap.NewNop(),
|
Logger: zap.NewNop(),
|
||||||
Broadcast: netSrv.BroadcastExtensible,
|
Broadcast: netSrv.BroadcastExtensible,
|
||||||
Chain: chain,
|
Chain: chain,
|
||||||
ProtocolConfiguration: chain.GetConfig(),
|
ProtocolConfiguration: cfg.ProtocolConfiguration,
|
||||||
RequestTx: netSrv.RequestTx,
|
RequestTx: netSrv.RequestTx,
|
||||||
StopTxFlow: netSrv.StopTxFlow,
|
StopTxFlow: netSrv.StopTxFlow,
|
||||||
Wallet: cfg.ApplicationConfiguration.Consensus.UnlockWallet,
|
Wallet: cfg.ApplicationConfiguration.Consensus.UnlockWallet,
|
||||||
|
|
|
@ -12,6 +12,8 @@ import (
|
||||||
|
|
||||||
// ApplicationConfiguration config specific to the node.
|
// ApplicationConfiguration config specific to the node.
|
||||||
type ApplicationConfiguration struct {
|
type ApplicationConfiguration struct {
|
||||||
|
Ledger `yaml:",inline"`
|
||||||
|
|
||||||
// Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
|
// Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
|
||||||
Address *string `yaml:"Address,omitempty"`
|
Address *string `yaml:"Address,omitempty"`
|
||||||
// Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
|
// Deprecated: please, use Addresses field of P2P section instead, this field will be removed in future versions.
|
||||||
|
|
|
@ -35,6 +35,15 @@ func (c Config) GenerateUserAgent() string {
|
||||||
return fmt.Sprintf(UserAgentFormat, Version)
|
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
|
// Load attempts to load the config from the given
|
||||||
// path for the given netMode.
|
// path for the given netMode.
|
||||||
func Load(path string, netMode netmode.Magic) (Config, error) {
|
func Load(path string, netMode netmode.Magic) (Config, error) {
|
||||||
|
|
28
pkg/config/ledger_config.go
Normal file
28
pkg/config/ledger_config.go
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ type (
|
||||||
// GarbageCollectionPeriod sets the number of blocks to wait before
|
// GarbageCollectionPeriod sets the number of blocks to wait before
|
||||||
// starting the next MPT garbage collection cycle when RemoveUntraceableBlocks
|
// starting the next MPT garbage collection cycle when RemoveUntraceableBlocks
|
||||||
// option is used.
|
// option is used.
|
||||||
|
//
|
||||||
|
// Deprecated: please use the same setting in the ApplicationConfiguration, this field will be removed in future versions.
|
||||||
GarbageCollectionPeriod uint32 `yaml:"GarbageCollectionPeriod"`
|
GarbageCollectionPeriod uint32 `yaml:"GarbageCollectionPeriod"`
|
||||||
|
|
||||||
Magic netmode.Magic `yaml:"Magic"`
|
Magic netmode.Magic `yaml:"Magic"`
|
||||||
|
@ -35,8 +37,12 @@ type (
|
||||||
// KeepOnlyLatestState specifies if MPT should only store the latest state.
|
// KeepOnlyLatestState specifies if MPT should only store the latest state.
|
||||||
// If true, DB size will be smaller, but older roots won't be accessible.
|
// 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 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"`
|
KeepOnlyLatestState bool `yaml:"KeepOnlyLatestState"`
|
||||||
// RemoveUntraceableBlocks specifies if old data should be removed.
|
// 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"`
|
RemoveUntraceableBlocks bool `yaml:"RemoveUntraceableBlocks"`
|
||||||
// MaxBlockSize is the maximum block size in bytes.
|
// MaxBlockSize is the maximum block size in bytes.
|
||||||
MaxBlockSize uint32 `yaml:"MaxBlockSize"`
|
MaxBlockSize uint32 `yaml:"MaxBlockSize"`
|
||||||
|
@ -59,6 +65,8 @@ type (
|
||||||
// ReservedAttributes allows to have reserved attributes range for experimental or private purposes.
|
// ReservedAttributes allows to have reserved attributes range for experimental or private purposes.
|
||||||
ReservedAttributes bool `yaml:"ReservedAttributes"`
|
ReservedAttributes bool `yaml:"ReservedAttributes"`
|
||||||
// SaveStorageBatch enables storage batch saving before every persist.
|
// 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"`
|
SaveStorageBatch bool `yaml:"SaveStorageBatch"`
|
||||||
// SecondsPerBlock is the time interval (in seconds) between blocks that consensus nodes work with.
|
// 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).
|
// Validators stores history of changes to consensus node number (height: number).
|
||||||
ValidatorsHistory map[uint32]int `yaml:"ValidatorsHistory"`
|
ValidatorsHistory map[uint32]int `yaml:"ValidatorsHistory"`
|
||||||
// Whether to verify received blocks.
|
// 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"`
|
VerifyBlocks bool `yaml:"VerifyBlocks"`
|
||||||
// Whether to verify transactions in the received blocks.
|
// Whether to verify transactions in the received blocks.
|
||||||
VerifyTransactions bool `yaml:"VerifyTransactions"`
|
VerifyTransactions bool `yaml:"VerifyTransactions"`
|
||||||
|
|
|
@ -44,7 +44,7 @@ const nsInMs = 1000000
|
||||||
type Ledger interface {
|
type Ledger interface {
|
||||||
AddBlock(block *coreb.Block) error
|
AddBlock(block *coreb.Block) error
|
||||||
ApplyPolicyToTxSet([]*transaction.Transaction) []*transaction.Transaction
|
ApplyPolicyToTxSet([]*transaction.Transaction) []*transaction.Transaction
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetMemPool() *mempool.Pool
|
GetMemPool() *mempool.Pool
|
||||||
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
||||||
GetStateRoot(height uint32) (*state.MPTRoot, 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 validators keys.PublicKeys
|
||||||
var err error
|
var err error
|
||||||
cfg := s.Chain.GetConfig()
|
cfg := s.Chain.GetConfig().ProtocolConfiguration
|
||||||
if cfg.ShouldUpdateCommitteeAt(ctx.BlockIndex) {
|
if cfg.ShouldUpdateCommitteeAt(ctx.BlockIndex) {
|
||||||
validators, err = s.Chain.GetValidators()
|
validators, err = s.Chain.GetValidators()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -50,7 +50,7 @@ func TestNewWatchingService(t *testing.T) {
|
||||||
Logger: zaptest.NewLogger(t),
|
Logger: zaptest.NewLogger(t),
|
||||||
Broadcast: func(*npayload.Extensible) {},
|
Broadcast: func(*npayload.Extensible) {},
|
||||||
Chain: bc,
|
Chain: bc,
|
||||||
ProtocolConfiguration: bc.GetConfig(),
|
ProtocolConfiguration: bc.GetConfig().ProtocolConfiguration,
|
||||||
RequestTx: func(...util.Uint256) {},
|
RequestTx: func(...util.Uint256) {},
|
||||||
StopTxFlow: func() {},
|
StopTxFlow: func() {},
|
||||||
TimePerBlock: bc.GetConfig().TimePerBlock,
|
TimePerBlock: bc.GetConfig().TimePerBlock,
|
||||||
|
@ -495,7 +495,7 @@ func newTestServiceWithChain(t *testing.T, bc *core.Blockchain) *service {
|
||||||
Logger: zaptest.NewLogger(t),
|
Logger: zaptest.NewLogger(t),
|
||||||
Broadcast: func(*npayload.Extensible) {},
|
Broadcast: func(*npayload.Extensible) {},
|
||||||
Chain: bc,
|
Chain: bc,
|
||||||
ProtocolConfiguration: bc.GetConfig(),
|
ProtocolConfiguration: bc.GetConfig().ProtocolConfiguration,
|
||||||
RequestTx: func(...util.Uint256) {},
|
RequestTx: func(...util.Uint256) {},
|
||||||
StopTxFlow: func() {},
|
StopTxFlow: func() {},
|
||||||
TimePerBlock: bc.GetConfig().TimePerBlock,
|
TimePerBlock: bc.GetConfig().TimePerBlock,
|
||||||
|
@ -519,7 +519,7 @@ func newSingleTestChain(t *testing.T) *core.Blockchain {
|
||||||
cfg, err := config.LoadFile(configPath)
|
cfg, err := config.LoadFile(configPath)
|
||||||
require.NoError(t, err, "could not load config")
|
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")
|
require.NoError(t, err, "could not create chain")
|
||||||
|
|
||||||
go chain.Run()
|
go chain.Run()
|
||||||
|
@ -532,7 +532,7 @@ func newTestChain(t *testing.T, stateRootInHeader bool) *core.Blockchain {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
unitTestNetCfg.ProtocolConfiguration.StateRootInHeader = stateRootInHeader
|
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)
|
require.NoError(t, err)
|
||||||
|
|
||||||
go chain.Run()
|
go chain.Run()
|
||||||
|
|
|
@ -37,7 +37,7 @@ var (
|
||||||
func TestCreateBasicChain(t *testing.T) {
|
func TestCreateBasicChain(t *testing.T) {
|
||||||
const saveChain = false
|
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
|
cfg.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, validators, committee)
|
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
|
|
@ -116,7 +116,7 @@ var (
|
||||||
type Blockchain struct {
|
type Blockchain struct {
|
||||||
HeaderHashes
|
HeaderHashes
|
||||||
|
|
||||||
config config.ProtocolConfiguration
|
config config.Blockchain
|
||||||
|
|
||||||
// The only way chain state changes is by adding blocks, so we can't
|
// 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
|
// 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
|
// NewBlockchain returns a new blockchain object the will use the
|
||||||
// given Store as its underlying storage. For it to work correctly you need
|
// given Store as its underlying storage. For it to work correctly you need
|
||||||
// to spawn a goroutine for its Run method after this initialization.
|
// 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 {
|
if log == nil {
|
||||||
return nil, errors.New("empty logger")
|
return nil, errors.New("empty logger")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Protocol configuration fixups/checks.
|
||||||
if cfg.InitialGASSupply <= 0 {
|
if cfg.InitialGASSupply <= 0 {
|
||||||
cfg.InitialGASSupply = fixedn.Fixed8(defaultInitialGAS)
|
cfg.InitialGASSupply = fixedn.Fixed8(defaultInitialGAS)
|
||||||
log.Info("initial gas supply is not set or wrong, setting default value", zap.String("InitialGASSupply", cfg.InitialGASSupply.String()))
|
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))
|
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 {
|
if len(cfg.NativeUpdateHistories) == 0 {
|
||||||
cfg.NativeUpdateHistories = map[string][]uint32{}
|
cfg.NativeUpdateHistories = map[string][]uint32{}
|
||||||
log.Info("NativeActivations are not set, using default values")
|
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{}
|
cfg.Hardforks = map[string]uint32{}
|
||||||
log.Info("Hardforks are not set, using default value")
|
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{
|
bc := &Blockchain{
|
||||||
config: cfg,
|
config: cfg,
|
||||||
dao: dao.NewSimple(s, cfg.StateRootInHeader, cfg.P2PSigExtensions),
|
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),
|
events: make(chan bcEvent),
|
||||||
subCh: make(chan interface{}),
|
subCh: make(chan interface{}),
|
||||||
unsubCh: 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
|
bc.contracts.Designate.StateRootService = bc.stateRoot
|
||||||
|
|
||||||
if err := bc.init(); err != nil {
|
if err := bc.init(); err != nil {
|
||||||
|
@ -370,13 +381,13 @@ func (bc *Blockchain) init() error {
|
||||||
StateRootInHeader: bc.config.StateRootInHeader,
|
StateRootInHeader: bc.config.StateRootInHeader,
|
||||||
P2PSigExtensions: bc.config.P2PSigExtensions,
|
P2PSigExtensions: bc.config.P2PSigExtensions,
|
||||||
P2PStateExchangeExtensions: bc.config.P2PStateExchangeExtensions,
|
P2PStateExchangeExtensions: bc.config.P2PStateExchangeExtensions,
|
||||||
KeepOnlyLatestState: bc.config.KeepOnlyLatestState,
|
KeepOnlyLatestState: bc.config.Ledger.KeepOnlyLatestState,
|
||||||
Value: version,
|
Value: version,
|
||||||
}
|
}
|
||||||
bc.dao.PutVersion(ver)
|
bc.dao.PutVersion(ver)
|
||||||
bc.dao.Version = ver
|
bc.dao.Version = ver
|
||||||
bc.persistent.Version = ver
|
bc.persistent.Version = ver
|
||||||
genesisBlock, err := CreateGenesisBlock(bc.config)
|
genesisBlock, err := CreateGenesisBlock(bc.config.ProtocolConfiguration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -401,9 +412,9 @@ func (bc *Blockchain) init() error {
|
||||||
return fmt.Errorf("P2PStateExchangeExtensions setting mismatch (old=%t, new=%t)",
|
return fmt.Errorf("P2PStateExchangeExtensions setting mismatch (old=%t, new=%t)",
|
||||||
ver.P2PStateExchangeExtensions, bc.config.P2PStateExchangeExtensions)
|
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)",
|
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.dao.Version = ver
|
||||||
bc.persistent.Version = ver
|
bc.persistent.Version = ver
|
||||||
|
@ -432,7 +443,7 @@ func (bc *Blockchain) init() error {
|
||||||
if (stateChStage[0] & stateResetBit) != 0 {
|
if (stateChStage[0] & stateResetBit) != 0 {
|
||||||
return bc.resetStateInternal(stateSyncPoint, stateChangeStage(stateChStage[0]&(^stateResetBit)))
|
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. " +
|
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")
|
"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))
|
bc.log.Info("chain is at the proper state", zap.Uint32("height", height))
|
||||||
return nil
|
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)
|
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")
|
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
|
pStorageStart := p
|
||||||
|
|
||||||
var mode = mpt.ModeAll
|
var mode = mpt.ModeAll
|
||||||
if bc.config.RemoveUntraceableBlocks {
|
if bc.config.Ledger.RemoveUntraceableBlocks {
|
||||||
mode |= mpt.ModeGCFlag
|
mode |= mpt.ModeGCFlag
|
||||||
}
|
}
|
||||||
trieStore := mpt.NewTrieStore(sr.Root, mode, cache.Store)
|
trieStore := mpt.NewTrieStore(sr.Root, mode, cache.Store)
|
||||||
|
@ -919,14 +930,14 @@ func (bc *Blockchain) Run() {
|
||||||
var oldPersisted uint32
|
var oldPersisted uint32
|
||||||
var gcDur time.Duration
|
var gcDur time.Duration
|
||||||
|
|
||||||
if bc.config.RemoveUntraceableBlocks {
|
if bc.config.Ledger.RemoveUntraceableBlocks {
|
||||||
oldPersisted = atomic.LoadUint32(&bc.persistedHeight)
|
oldPersisted = atomic.LoadUint32(&bc.persistedHeight)
|
||||||
}
|
}
|
||||||
dur, err := bc.persist(nextSync)
|
dur, err := bc.persist(nextSync)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bc.log.Warn("failed to persist blockchain", zap.Error(err))
|
bc.log.Warn("failed to persist blockchain", zap.Error(err))
|
||||||
}
|
}
|
||||||
if bc.config.RemoveUntraceableBlocks {
|
if bc.config.Ledger.RemoveUntraceableBlocks {
|
||||||
gcDur = bc.tryRunGC(oldPersisted)
|
gcDur = bc.tryRunGC(oldPersisted)
|
||||||
}
|
}
|
||||||
nextSync = dur > persistInterval*2
|
nextSync = dur > persistInterval*2
|
||||||
|
@ -955,14 +966,14 @@ func (bc *Blockchain) tryRunGC(oldHeight uint32) time.Duration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Always round to the GCP.
|
// Always round to the GCP.
|
||||||
tgtBlock /= int64(bc.config.GarbageCollectionPeriod)
|
tgtBlock /= int64(bc.config.Ledger.GarbageCollectionPeriod)
|
||||||
tgtBlock *= int64(bc.config.GarbageCollectionPeriod)
|
tgtBlock *= int64(bc.config.Ledger.GarbageCollectionPeriod)
|
||||||
// Count periods.
|
// Count periods.
|
||||||
oldHeight /= bc.config.GarbageCollectionPeriod
|
oldHeight /= bc.config.Ledger.GarbageCollectionPeriod
|
||||||
newHeight /= bc.config.GarbageCollectionPeriod
|
newHeight /= bc.config.Ledger.GarbageCollectionPeriod
|
||||||
if tgtBlock > int64(bc.config.GarbageCollectionPeriod) && newHeight != oldHeight {
|
if tgtBlock > int64(bc.config.Ledger.GarbageCollectionPeriod) && newHeight != oldHeight {
|
||||||
tgtBlock /= int64(bc.config.GarbageCollectionPeriod)
|
tgtBlock /= int64(bc.config.Ledger.GarbageCollectionPeriod)
|
||||||
tgtBlock *= int64(bc.config.GarbageCollectionPeriod)
|
tgtBlock *= int64(bc.config.Ledger.GarbageCollectionPeriod)
|
||||||
dur = bc.stateRoot.GC(uint32(tgtBlock), bc.store)
|
dur = bc.stateRoot.GC(uint32(tgtBlock), bc.store)
|
||||||
dur += bc.removeOldTransfers(uint32(tgtBlock))
|
dur += bc.removeOldTransfers(uint32(tgtBlock))
|
||||||
}
|
}
|
||||||
|
@ -1298,12 +1309,12 @@ func (bc *Blockchain) AddBlock(block *block.Block) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if block.Index == bc.HeaderHeight()+1 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if bc.config.VerifyBlocks {
|
if bc.config.Ledger.VerifyBlocks {
|
||||||
merkle := block.ComputeMerkleRoot()
|
merkle := block.ComputeMerkleRoot()
|
||||||
if !block.MerkleRoot.Equals(merkle) {
|
if !block.MerkleRoot.Equals(merkle) {
|
||||||
return errors.New("invalid block: MerkleRoot mismatch")
|
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
|
// AddHeaders processes the given headers and add them to the
|
||||||
// HeaderHashList. It expects headers to be sorted by index.
|
// HeaderHashList. It expects headers to be sorted by index.
|
||||||
func (bc *Blockchain) AddHeaders(headers ...*block.Header) error {
|
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
|
// 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)
|
transCache = make(map[util.Uint160]transferData)
|
||||||
)
|
)
|
||||||
kvcache.StoreAsCurrentBlock(block)
|
kvcache.StoreAsCurrentBlock(block)
|
||||||
if bc.config.RemoveUntraceableBlocks {
|
if bc.config.Ledger.RemoveUntraceableBlocks {
|
||||||
var start, stop uint32
|
var start, stop uint32
|
||||||
if bc.config.P2PStateExchangeExtensions {
|
if bc.config.P2PStateExchangeExtensions {
|
||||||
// remove batch of old blocks starting from P2-MaxTraceableBlocks-StateSyncInterval up to P2-MaxTraceableBlocks
|
// 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()
|
bc.lastBatch = cache.GetBatch()
|
||||||
}
|
}
|
||||||
// Every persist cycle we also compact our in-memory MPT. It's flushed
|
// 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 {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
if _, ok := info.LastUpdated[bc.contracts.NEO.ID]; !ok {
|
||||||
nBalance, lub := bc.contracts.NEO.BalanceOf(bc.dao, acc)
|
nBalance, lub := bc.contracts.NEO.BalanceOf(bc.dao, acc)
|
||||||
if nBalance.Sign() != 0 {
|
if nBalance.Sign() != 0 {
|
||||||
|
@ -2121,7 +2132,7 @@ func (bc *Blockchain) GetNatives() []state.NativeContract {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConfig returns the config stored in the blockchain.
|
// GetConfig returns the config stored in the blockchain.
|
||||||
func (bc *Blockchain) GetConfig() config.ProtocolConfiguration {
|
func (bc *Blockchain) GetConfig() config.Blockchain {
|
||||||
return bc.config
|
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.
|
// 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) {
|
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")
|
return nil, errors.New("only latest state is supported")
|
||||||
}
|
}
|
||||||
b, err := bc.getFakeNextBlock(nextBlockHeight)
|
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)
|
return nil, fmt.Errorf("failed to create fake block for height %d: %w", nextBlockHeight, err)
|
||||||
}
|
}
|
||||||
var mode = mpt.ModeAll
|
var mode = mpt.ModeAll
|
||||||
if bc.config.RemoveUntraceableBlocks {
|
if bc.config.Ledger.RemoveUntraceableBlocks {
|
||||||
if b.Index < bc.BlockHeight()-bc.config.MaxTraceableBlocks {
|
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)
|
return nil, fmt.Errorf("state for height %d is outdated and removed from the storage", b.Index)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,21 +32,21 @@ func TestVerifyHeader(t *testing.T) {
|
||||||
t.Run("Hash", func(t *testing.T) {
|
t.Run("Hash", func(t *testing.T) {
|
||||||
h := prev.Hash()
|
h := prev.Hash()
|
||||||
h[0] = ^h[0]
|
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))
|
require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrHashMismatch))
|
||||||
})
|
})
|
||||||
t.Run("Index", func(t *testing.T) {
|
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))
|
require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrIndexMismatch))
|
||||||
})
|
})
|
||||||
t.Run("Timestamp", func(t *testing.T) {
|
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
|
hdr.Timestamp = 0
|
||||||
require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrInvalidTimestamp))
|
require.True(t, errors.Is(bc.verifyHeader(&hdr, &prev), ErrHdrInvalidTimestamp))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("Valid", func(t *testing.T) {
|
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))
|
require.NoError(t, bc.verifyHeader(&hdr, &prev))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -144,12 +144,12 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) {
|
||||||
maxTraceable uint32 = 6
|
maxTraceable uint32 = 6
|
||||||
)
|
)
|
||||||
spountCfg := func(c *config.Config) {
|
spountCfg := func(c *config.Config) {
|
||||||
c.ProtocolConfiguration.RemoveUntraceableBlocks = true
|
c.ApplicationConfiguration.RemoveUntraceableBlocks = true
|
||||||
c.ProtocolConfiguration.StateRootInHeader = true
|
c.ProtocolConfiguration.StateRootInHeader = true
|
||||||
c.ProtocolConfiguration.P2PStateExchangeExtensions = true
|
c.ProtocolConfiguration.P2PStateExchangeExtensions = true
|
||||||
c.ProtocolConfiguration.StateSyncInterval = stateSyncInterval
|
c.ProtocolConfiguration.StateSyncInterval = stateSyncInterval
|
||||||
c.ProtocolConfiguration.MaxTraceableBlocks = maxTraceable
|
c.ProtocolConfiguration.MaxTraceableBlocks = maxTraceable
|
||||||
c.ProtocolConfiguration.KeepOnlyLatestState = true
|
c.ApplicationConfiguration.KeepOnlyLatestState = true
|
||||||
}
|
}
|
||||||
bcSpout := newTestChainWithCustomCfg(t, spountCfg)
|
bcSpout := newTestChainWithCustomCfg(t, spountCfg)
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
cfg(&unitTestNetCfg)
|
cfg(&unitTestNetCfg)
|
||||||
log := zaptest.NewLogger(t)
|
log := zaptest.NewLogger(t)
|
||||||
_, err = NewBlockchain(store, unitTestNetCfg.ProtocolConfiguration, log)
|
_, err = NewBlockchain(store, unitTestNetCfg.Blockchain(), log)
|
||||||
if len(errText) != 0 {
|
if len(errText) != 0 {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, strings.Contains(err.Error(), errText))
|
require.True(t, strings.Contains(err.Error(), errText))
|
||||||
|
@ -200,7 +200,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) {
|
||||||
}
|
}
|
||||||
boltCfg := func(c *config.Config) {
|
boltCfg := func(c *config.Config) {
|
||||||
spountCfg(c)
|
spountCfg(c)
|
||||||
c.ProtocolConfiguration.KeepOnlyLatestState = true
|
c.ApplicationConfiguration.KeepOnlyLatestState = true
|
||||||
}
|
}
|
||||||
// manually store statejump stage to check statejump recover process
|
// manually store statejump stage to check statejump recover process
|
||||||
bPrefix[0] = byte(storage.SYSStateChangeStage)
|
bPrefix[0] = byte(storage.SYSStateChangeStage)
|
||||||
|
@ -219,7 +219,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) {
|
||||||
bcSpout.dao.Store.Put([]byte{byte(storage.SYSStateSyncPoint)}, point)
|
bcSpout.dao.Store.Put([]byte{byte(storage.SYSStateSyncPoint)}, point)
|
||||||
checkNewBlockchainErr(t, func(c *config.Config) {
|
checkNewBlockchainErr(t, func(c *config.Config) {
|
||||||
boltCfg(c)
|
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")
|
}, 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) {
|
t.Run("invalid state sync point", func(t *testing.T) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ func newLevelDBForTestingWithPath(t testing.TB, dbPath string) (storage.Store, s
|
||||||
|
|
||||||
func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
ps, path := newLevelDBForTestingWithPath(t, "")
|
ps, path := newLevelDBForTestingWithPath(t, "")
|
||||||
customConfig := func(c *config.ProtocolConfiguration) {
|
customConfig := func(c *config.Blockchain) {
|
||||||
c.StateRootInHeader = true // Need for P2PStateExchangeExtensions check.
|
c.StateRootInHeader = true // Need for P2PStateExchangeExtensions check.
|
||||||
c.P2PSigExtensions = true // Need for basic chain initializer.
|
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) {
|
t.Run("mismatch StateRootInHeader", func(t *testing.T) {
|
||||||
ps = newPS(t)
|
ps = newPS(t)
|
||||||
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) {
|
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) {
|
||||||
customConfig(c)
|
customConfig(c)
|
||||||
c.StateRootInHeader = false
|
c.StateRootInHeader = false
|
||||||
}, ps)
|
}, ps)
|
||||||
|
@ -115,7 +115,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("mismatch P2PSigExtensions", func(t *testing.T) {
|
t.Run("mismatch P2PSigExtensions", func(t *testing.T) {
|
||||||
ps = newPS(t)
|
ps = newPS(t)
|
||||||
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) {
|
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) {
|
||||||
customConfig(c)
|
customConfig(c)
|
||||||
c.P2PSigExtensions = false
|
c.P2PSigExtensions = false
|
||||||
}, ps)
|
}, ps)
|
||||||
|
@ -124,7 +124,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("mismatch P2PStateExchangeExtensions", func(t *testing.T) {
|
t.Run("mismatch P2PStateExchangeExtensions", func(t *testing.T) {
|
||||||
ps = newPS(t)
|
ps = newPS(t)
|
||||||
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) {
|
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) {
|
||||||
customConfig(c)
|
customConfig(c)
|
||||||
c.StateRootInHeader = true
|
c.StateRootInHeader = true
|
||||||
c.P2PStateExchangeExtensions = true
|
c.P2PStateExchangeExtensions = true
|
||||||
|
@ -134,9 +134,9 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("mismatch KeepOnlyLatestState", func(t *testing.T) {
|
t.Run("mismatch KeepOnlyLatestState", func(t *testing.T) {
|
||||||
ps = newPS(t)
|
ps = newPS(t)
|
||||||
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) {
|
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) {
|
||||||
customConfig(c)
|
customConfig(c)
|
||||||
c.KeepOnlyLatestState = true
|
c.Ledger.KeepOnlyLatestState = true
|
||||||
}, ps)
|
}, ps)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, strings.Contains(err.Error(), "KeepOnlyLatestState setting mismatch"), 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) {
|
t.Run("invalid native contract deactivation", func(t *testing.T) {
|
||||||
ps = newPS(t)
|
ps = newPS(t)
|
||||||
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.ProtocolConfiguration) {
|
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) {
|
||||||
customConfig(c)
|
customConfig(c)
|
||||||
c.NativeUpdateHistories = map[string][]uint32{
|
c.NativeUpdateHistories = map[string][]uint32{
|
||||||
nativenames.Policy: {0},
|
nativenames.Policy: {0},
|
||||||
|
@ -291,7 +291,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockchain_AddHeaders(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
|
c.StateRootInHeader = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
|
@ -342,7 +342,7 @@ func TestBlockchain_AddHeaders(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockchain_AddBlockStateRoot(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
|
c.StateRootInHeader = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
|
@ -371,7 +371,7 @@ func TestBlockchain_AddBlockStateRoot(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockchain_AddHeadersStateRoot(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
|
c.StateRootInHeader = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
|
@ -401,7 +401,7 @@ func TestBlockchain_AddHeadersStateRoot(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockchain_AddBadBlock(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)
|
bc, _ := chain.NewSingleWithCustomConfig(t, cfg)
|
||||||
err := bc.AddBlock(b)
|
err := bc.AddBlock(b)
|
||||||
if cfg == nil {
|
if cfg == nil {
|
||||||
|
@ -420,25 +420,25 @@ func TestBlockchain_AddBadBlock(t *testing.T) {
|
||||||
b := e.NewUnsignedBlock(t, tx)
|
b := e.NewUnsignedBlock(t, tx)
|
||||||
e.SignBlock(b)
|
e.SignBlock(b)
|
||||||
check(t, b, nil)
|
check(t, b, nil)
|
||||||
check(t, b, func(c *config.ProtocolConfiguration) {
|
check(t, b, func(c *config.Blockchain) {
|
||||||
c.VerifyBlocks = false
|
c.Ledger.VerifyBlocks = false
|
||||||
})
|
})
|
||||||
|
|
||||||
b = e.NewUnsignedBlock(t)
|
b = e.NewUnsignedBlock(t)
|
||||||
b.PrevHash = util.Uint256{} // Intentionally make block invalid.
|
b.PrevHash = util.Uint256{} // Intentionally make block invalid.
|
||||||
e.SignBlock(b)
|
e.SignBlock(b)
|
||||||
check(t, b, nil)
|
check(t, b, nil)
|
||||||
check(t, b, func(c *config.ProtocolConfiguration) {
|
check(t, b, func(c *config.Blockchain) {
|
||||||
c.VerifyBlocks = false
|
c.Ledger.VerifyBlocks = false
|
||||||
})
|
})
|
||||||
|
|
||||||
tx = e.NewUnsignedTx(t, neoHash, "transfer", acc.ScriptHash(), util.Uint160{1, 2, 3}, 1, nil) // Check the good tx.
|
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)
|
e.SignTx(t, tx, -1, acc)
|
||||||
b = e.NewUnsignedBlock(t, tx)
|
b = e.NewUnsignedBlock(t, tx)
|
||||||
e.SignBlock(b)
|
e.SignBlock(b)
|
||||||
check(t, b, func(c *config.ProtocolConfiguration) {
|
check(t, b, func(c *config.Blockchain) {
|
||||||
c.VerifyTransactions = true
|
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) {
|
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
|
c.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
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) {
|
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.MaxTraceableBlocks = 2
|
||||||
c.GarbageCollectionPeriod = 2
|
c.Ledger.GarbageCollectionPeriod = 2
|
||||||
c.RemoveUntraceableBlocks = true
|
c.Ledger.RemoveUntraceableBlocks = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
neoValidatorInvoker := e.ValidatorInvoker(e.NativeHash(t, nativenames.Neo))
|
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)
|
check(t, bc, tx1Hash, b1.Hash(), sRoot.Root, true)
|
||||||
})
|
})
|
||||||
t.Run("P2PStateExchangeExtensions on", func(t *testing.T) {
|
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.MaxTraceableBlocks = 2
|
||||||
c.GarbageCollectionPeriod = 2
|
c.Ledger.GarbageCollectionPeriod = 2
|
||||||
c.RemoveUntraceableBlocks = true
|
c.Ledger.RemoveUntraceableBlocks = true
|
||||||
c.P2PStateExchangeExtensions = true
|
c.P2PStateExchangeExtensions = true
|
||||||
c.StateSyncInterval = 2
|
c.StateSyncInterval = 2
|
||||||
c.StateRootInHeader = true
|
c.StateRootInHeader = true
|
||||||
|
@ -1047,7 +1047,7 @@ func TestConfigNativeUpdateHistory(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockchain_VerifyTx(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.P2PSigExtensions = true
|
||||||
c.ReservedAttributes = true
|
c.ReservedAttributes = true
|
||||||
})
|
})
|
||||||
|
@ -1467,7 +1467,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
t.Run("Disabled", func(t *testing.T) {
|
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.P2PSigExtensions = false
|
||||||
c.ReservedAttributes = false
|
c.ReservedAttributes = false
|
||||||
})
|
})
|
||||||
|
@ -1509,7 +1509,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
t.Run("Disabled", func(t *testing.T) {
|
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.P2PSigExtensions = false
|
||||||
c.ReservedAttributes = false
|
c.ReservedAttributes = false
|
||||||
})
|
})
|
||||||
|
@ -1553,7 +1553,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
t.Run("disabled", func(t *testing.T) {
|
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.P2PSigExtensions = false
|
||||||
c.ReservedAttributes = false
|
c.ReservedAttributes = false
|
||||||
})
|
})
|
||||||
|
@ -1649,7 +1649,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
t.Run("Disabled", func(t *testing.T) {
|
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.P2PSigExtensions = false
|
||||||
c.ReservedAttributes = false
|
c.ReservedAttributes = false
|
||||||
})
|
})
|
||||||
|
@ -1909,7 +1909,7 @@ func TestBlockchain_Bug1728(t *testing.T) {
|
||||||
|
|
||||||
func TestBlockchain_ResetStateErrors(t *testing.T) {
|
func TestBlockchain_ResetStateErrors(t *testing.T) {
|
||||||
chainHeight := 3
|
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())
|
db, path := newLevelDBForTestingWithPath(t, t.TempDir())
|
||||||
bc, validators, committee := chain.NewMultiWithCustomConfigAndStore(t, cfg, db, false)
|
bc, validators, committee := chain.NewMultiWithCustomConfigAndStore(t, cfg, db, false)
|
||||||
e := neotest.NewExecutor(t, bc, validators, committee)
|
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
@ -1937,13 +1937,13 @@ func TestBlockchain_ResetStateErrors(t *testing.T) {
|
||||||
checkResetErr(t, nil, uint32(chainHeight), "")
|
checkResetErr(t, nil, uint32(chainHeight), "")
|
||||||
})
|
})
|
||||||
t.Run("KeepOnlyLatestState is enabled", func(t *testing.T) {
|
t.Run("KeepOnlyLatestState is enabled", func(t *testing.T) {
|
||||||
checkResetErr(t, func(c *config.ProtocolConfiguration) {
|
checkResetErr(t, func(c *config.Blockchain) {
|
||||||
c.KeepOnlyLatestState = true
|
c.Ledger.KeepOnlyLatestState = true
|
||||||
}, uint32(chainHeight-1), "KeepOnlyLatestState is enabled")
|
}, uint32(chainHeight-1), "KeepOnlyLatestState is enabled")
|
||||||
})
|
})
|
||||||
t.Run("some blocks where removed", func(t *testing.T) {
|
t.Run("some blocks where removed", func(t *testing.T) {
|
||||||
checkResetErr(t, func(c *config.ProtocolConfiguration) {
|
checkResetErr(t, func(c *config.Blockchain) {
|
||||||
c.RemoveUntraceableBlocks = true
|
c.Ledger.RemoveUntraceableBlocks = true
|
||||||
c.MaxTraceableBlocks = 2
|
c.MaxTraceableBlocks = 2
|
||||||
}, uint32(chainHeight-3), "RemoveUntraceableBlocks is enabled, a necessary batch of traceable blocks has already been removed")
|
}, 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) {
|
func TestBlockchain_ResetState(t *testing.T) {
|
||||||
// Create the DB.
|
// Create the DB.
|
||||||
db, path := newLevelDBForTestingWithPath(t, t.TempDir())
|
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
|
cfg.P2PSigExtensions = true
|
||||||
}, db, false)
|
}, db, false)
|
||||||
go bc.Run()
|
go bc.Run()
|
||||||
|
@ -2025,7 +2025,7 @@ func TestBlockchain_ResetState(t *testing.T) {
|
||||||
|
|
||||||
// Start new chain with existing DB, but do not run it.
|
// Start new chain with existing DB, but do not run it.
|
||||||
db, _ = newLevelDBForTestingWithPath(t, path)
|
db, _ = newLevelDBForTestingWithPath(t, path)
|
||||||
bc, _, _ = chain.NewMultiWithCustomConfigAndStore(t, func(cfg *config.ProtocolConfiguration) {
|
bc, _, _ = chain.NewMultiWithCustomConfigAndStore(t, func(cfg *config.Blockchain) {
|
||||||
cfg.P2PSigExtensions = true
|
cfg.P2PSigExtensions = true
|
||||||
}, db, false)
|
}, db, false)
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
type DumperRestorer interface {
|
type DumperRestorer interface {
|
||||||
AddBlock(block *block.Block) error
|
AddBlock(block *block.Block) error
|
||||||
GetBlock(hash util.Uint256) (*block.Block, error)
|
GetBlock(hash util.Uint256) (*block.Block, error)
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetHeaderHash(uint32) util.Uint256
|
GetHeaderHash(uint32) util.Uint256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,30 +16,30 @@ import (
|
||||||
|
|
||||||
func TestBlockchain_DumpAndRestore(t *testing.T) {
|
func TestBlockchain_DumpAndRestore(t *testing.T) {
|
||||||
t.Run("no state root", func(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.StateRootInHeader = false
|
||||||
c.P2PSigExtensions = true
|
c.P2PSigExtensions = true
|
||||||
}, nil)
|
}, nil)
|
||||||
})
|
})
|
||||||
t.Run("with state root", func(t *testing.T) {
|
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.StateRootInHeader = true
|
||||||
c.P2PSigExtensions = true
|
c.P2PSigExtensions = true
|
||||||
}, nil)
|
}, nil)
|
||||||
})
|
})
|
||||||
t.Run("remove untraceable", func(t *testing.T) {
|
t.Run("remove untraceable", func(t *testing.T) {
|
||||||
// Dump can only be created if all blocks and transactions are present.
|
// 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
|
c.P2PSigExtensions = true
|
||||||
}, func(c *config.ProtocolConfiguration) {
|
}, func(c *config.Blockchain) {
|
||||||
c.MaxTraceableBlocks = 2
|
c.MaxTraceableBlocks = 2
|
||||||
c.RemoveUntraceableBlocks = true
|
c.Ledger.RemoveUntraceableBlocks = true
|
||||||
c.P2PSigExtensions = 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 {
|
if restoreF == nil {
|
||||||
restoreF = dumpF
|
restoreF = dumpF
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ func initTestChainNoCheck(t testing.TB, st storage.Store, f func(*config.Config)
|
||||||
if _, ok := t.(*testing.B); ok {
|
if _, ok := t.(*testing.B); ok {
|
||||||
log = zap.NewNop()
|
log = zap.NewNop()
|
||||||
}
|
}
|
||||||
return NewBlockchain(st, unitTestNetCfg.ProtocolConfiguration, log)
|
return NewBlockchain(st, unitTestNetCfg.Blockchain(), log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bc *Blockchain) newBlock(txs ...*transaction.Transaction) *block.Block {
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
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 {
|
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()
|
lastHash := bc.topBlock.Load().(*block.Block).Hash()
|
||||||
lastIndex := bc.topBlock.Load().(*block.Block).Index
|
lastIndex := bc.topBlock.Load().(*block.Block).Index
|
||||||
for i := 0; i < n; i++ {
|
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 {
|
if err := bc.AddBlock(blocks[i]); err != nil {
|
||||||
return blocks, err
|
return blocks, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ type Ledger interface {
|
||||||
BlockHeight() uint32
|
BlockHeight() uint32
|
||||||
CurrentBlockHash() util.Uint256
|
CurrentBlockHash() util.Uint256
|
||||||
GetBlock(hash util.Uint256) (*block.Block, error)
|
GetBlock(hash util.Uint256) (*block.Block, error)
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetHeaderHash(uint32) util.Uint256
|
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,
|
loadTokenFunc func(ic *Context, id int32) error,
|
||||||
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
|
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
|
||||||
dao := d.GetPrivate()
|
dao := d.GetPrivate()
|
||||||
cfg := bc.GetConfig()
|
cfg := bc.GetConfig().ProtocolConfiguration
|
||||||
return &Context{
|
return &Context{
|
||||||
Chain: bc,
|
Chain: bc,
|
||||||
Network: uint32(cfg.Magic),
|
Network: uint32(cfg.Magic),
|
||||||
|
|
|
@ -118,7 +118,7 @@ func TestCreateMultisigAccount(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateAccount_Hardfork(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.P2PSigExtensions = true // `basicchain.Init` requires Notary enabled
|
||||||
c.Hardforks = map[string]uint32{
|
c.Hardforks = map[string]uint32{
|
||||||
config.HFAspidochelone.String(): 2,
|
config.HFAspidochelone.String(): 2,
|
||||||
|
|
|
@ -90,7 +90,7 @@ func TestNativeContract_InvokeInternal(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("fail, bad NativeUpdateHistory height", func(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{
|
c.NativeUpdateHistories = map[string][]uint32{
|
||||||
nativenames.Policy: {0},
|
nativenames.Policy: {0},
|
||||||
nativenames.Neo: {0},
|
nativenames.Neo: {0},
|
||||||
|
|
|
@ -22,7 +22,7 @@ func TestManagement_GetNEP17Contracts(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("basic chain", func(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
|
c.P2PSigExtensions = true // `basicchain.Init` requires Notary enabled
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, validators, committee)
|
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
|
|
@ -65,7 +65,7 @@ func TestGAS_RewardWithP2PSigExtensionsEnabled(t *testing.T) {
|
||||||
nKeys = 4
|
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
|
cfg.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, validator, committee)
|
e := neotest.NewExecutor(t, bc, validator, committee)
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func newLedgerClient(t *testing.T) *neotest.ContractInvoker {
|
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
|
cfg.MaxTraceableBlocks = 10 // reduce number of traceable blocks for Ledger tests
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
|
|
|
@ -19,7 +19,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func newNotaryClient(t *testing.T) *neotest.ContractInvoker {
|
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
|
cfg.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||||
|
|
|
@ -55,12 +55,12 @@ type (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewModule returns new instance of stateroot module.
|
// 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
|
var mode mpt.TrieMode
|
||||||
if cfg.KeepOnlyLatestState {
|
if cfg.Ledger.KeepOnlyLatestState {
|
||||||
mode |= mpt.ModeLatest
|
mode |= mpt.ModeLatest
|
||||||
}
|
}
|
||||||
if cfg.RemoveUntraceableBlocks {
|
if cfg.Ledger.RemoveUntraceableBlocks {
|
||||||
mode |= mpt.ModeGC
|
mode |= mpt.ModeGC
|
||||||
}
|
}
|
||||||
return &Module{
|
return &Module{
|
||||||
|
|
|
@ -64,7 +64,7 @@ const (
|
||||||
type Ledger interface {
|
type Ledger interface {
|
||||||
AddHeaders(...*block.Header) error
|
AddHeaders(...*block.Header) error
|
||||||
BlockHeight() uint32
|
BlockHeight() uint32
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetHeader(hash util.Uint256) (*block.Header, error)
|
GetHeader(hash util.Uint256) (*block.Header, error)
|
||||||
GetHeaderHash(uint32) util.Uint256
|
GetHeaderHash(uint32) util.Uint256
|
||||||
HeaderHeight() uint32
|
HeaderHeight() uint32
|
||||||
|
@ -97,7 +97,7 @@ type Module struct {
|
||||||
|
|
||||||
// NewModule returns new instance of statesync module.
|
// 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 {
|
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{
|
return &Module{
|
||||||
dao: s,
|
dao: s,
|
||||||
bc: bc,
|
bc: bc,
|
||||||
|
@ -220,7 +220,7 @@ func (s *Module) defineSyncStage() error {
|
||||||
}
|
}
|
||||||
var mode mpt.TrieMode
|
var mode mpt.TrieMode
|
||||||
// No need to enable GC here, it only has latest things.
|
// 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
|
mode |= mpt.ModeLatest
|
||||||
}
|
}
|
||||||
s.billet = mpt.NewBillet(header.PrevStateRoot, mode,
|
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 {
|
if s.bc.GetConfig().StateRootInHeader != block.StateRootEnabled {
|
||||||
return fmt.Errorf("stateroot setting mismatch: %v != %v", 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()
|
merkle := block.ComputeMerkleRoot()
|
||||||
if !block.MerkleRoot.Equals(merkle) {
|
if !block.MerkleRoot.Equals(merkle) {
|
||||||
return errors.New("invalid block: MerkleRoot mismatch")
|
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
|
var mode mpt.TrieMode
|
||||||
// GC must be turned off here to allow access to the archived nodes.
|
// 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
|
mode |= mpt.ModeLatest
|
||||||
}
|
}
|
||||||
b := mpt.NewBillet(root, mode, 0, storage.NewMemCachedStore(s.dao.Store))
|
b := mpt.NewBillet(root, mode, 0, storage.NewMemCachedStore(s.dao.Store))
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestStateSyncModule_Init(t *testing.T) {
|
||||||
stateSyncInterval = 2
|
stateSyncInterval = 2
|
||||||
maxTraceable = 3
|
maxTraceable = 3
|
||||||
)
|
)
|
||||||
spoutCfg := func(c *config.ProtocolConfiguration) {
|
spoutCfg := func(c *config.Blockchain) {
|
||||||
c.StateRootInHeader = true
|
c.StateRootInHeader = true
|
||||||
c.P2PStateExchangeExtensions = true
|
c.P2PStateExchangeExtensions = true
|
||||||
c.StateSyncInterval = stateSyncInterval
|
c.StateSyncInterval = stateSyncInterval
|
||||||
|
@ -32,15 +32,15 @@ func TestStateSyncModule_Init(t *testing.T) {
|
||||||
e.AddNewBlock(t)
|
e.AddNewBlock(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
boltCfg := func(c *config.ProtocolConfiguration) {
|
boltCfg := func(c *config.Blockchain) {
|
||||||
spoutCfg(c)
|
spoutCfg(c)
|
||||||
c.KeepOnlyLatestState = true
|
c.Ledger.KeepOnlyLatestState = true
|
||||||
c.RemoveUntraceableBlocks = true
|
c.Ledger.RemoveUntraceableBlocks = true
|
||||||
}
|
}
|
||||||
t.Run("error: module disabled by config", func(t *testing.T) {
|
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)
|
boltCfg(c)
|
||||||
c.RemoveUntraceableBlocks = false
|
c.Ledger.RemoveUntraceableBlocks = false
|
||||||
})
|
})
|
||||||
module := bcBolt.GetStateSyncModule()
|
module := bcBolt.GetStateSyncModule()
|
||||||
require.Error(t, module.Init(bcSpout.BlockHeight())) // module inactive (non-archival node)
|
require.Error(t, module.Init(bcSpout.BlockHeight())) // module inactive (non-archival node)
|
||||||
|
@ -288,9 +288,9 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) {
|
||||||
maxTraceable = 6
|
maxTraceable = 6
|
||||||
stateSyncPoint = 24
|
stateSyncPoint = 24
|
||||||
)
|
)
|
||||||
spoutCfg := func(c *config.ProtocolConfiguration) {
|
spoutCfg := func(c *config.Blockchain) {
|
||||||
c.KeepOnlyLatestState = spoutEnableGC
|
c.Ledger.KeepOnlyLatestState = spoutEnableGC
|
||||||
c.RemoveUntraceableBlocks = spoutEnableGC
|
c.Ledger.RemoveUntraceableBlocks = spoutEnableGC
|
||||||
c.StateRootInHeader = true
|
c.StateRootInHeader = true
|
||||||
c.P2PStateExchangeExtensions = true
|
c.P2PStateExchangeExtensions = true
|
||||||
c.StateSyncInterval = stateSyncInterval
|
c.StateSyncInterval = stateSyncInterval
|
||||||
|
@ -309,10 +309,10 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) {
|
||||||
e.AddNewBlock(t)
|
e.AddNewBlock(t)
|
||||||
require.Equal(t, stateSyncPoint+2, int(bcSpout.BlockHeight()))
|
require.Equal(t, stateSyncPoint+2, int(bcSpout.BlockHeight()))
|
||||||
|
|
||||||
boltCfg := func(c *config.ProtocolConfiguration) {
|
boltCfg := func(c *config.Blockchain) {
|
||||||
spoutCfg(c)
|
spoutCfg(c)
|
||||||
c.KeepOnlyLatestState = true
|
c.Ledger.KeepOnlyLatestState = true
|
||||||
c.RemoveUntraceableBlocks = true
|
c.Ledger.RemoveUntraceableBlocks = true
|
||||||
}
|
}
|
||||||
bcBoltStore := storage.NewMemoryStore()
|
bcBoltStore := storage.NewMemoryStore()
|
||||||
bcBolt, _, _ := chain.NewMultiWithCustomConfigAndStore(t, boltCfg, bcBoltStore, false)
|
bcBolt, _, _ := chain.NewMultiWithCustomConfigAndStore(t, boltCfg, bcBoltStore, false)
|
||||||
|
|
|
@ -128,7 +128,7 @@ func NewSingle(t testing.TB) (*core.Blockchain, neotest.Signer) {
|
||||||
|
|
||||||
// NewSingleWithCustomConfig is similar to NewSingle, but allows to override the
|
// NewSingleWithCustomConfig is similar to NewSingle, but allows to override the
|
||||||
// default configuration.
|
// 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)
|
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
|
// Run method is called on the Blockchain instance. If not, it is its caller's
|
||||||
// responsibility to do that before using the chain and
|
// responsibility to do that before using the chain and
|
||||||
// to properly Close the chain when done.
|
// 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) {
|
func NewSingleWithCustomConfigAndStore(t testing.TB, f func(cfg *config.Blockchain), st storage.Store, run bool) (*core.Blockchain, neotest.Signer) {
|
||||||
protoCfg := config.ProtocolConfiguration{
|
var cfg = config.Blockchain{
|
||||||
Magic: netmode.UnitTestNet,
|
ProtocolConfiguration: config.ProtocolConfiguration{
|
||||||
MaxTraceableBlocks: MaxTraceableBlocks,
|
Magic: netmode.UnitTestNet,
|
||||||
TimePerBlock: TimePerBlock,
|
MaxTraceableBlocks: MaxTraceableBlocks,
|
||||||
StandbyCommittee: []string{hex.EncodeToString(committeeAcc.PublicKey().Bytes())},
|
TimePerBlock: TimePerBlock,
|
||||||
ValidatorsCount: 1,
|
StandbyCommittee: []string{hex.EncodeToString(committeeAcc.PublicKey().Bytes())},
|
||||||
VerifyBlocks: true,
|
ValidatorsCount: 1,
|
||||||
VerifyTransactions: true,
|
VerifyTransactions: true,
|
||||||
|
},
|
||||||
|
Ledger: config.Ledger{
|
||||||
|
VerifyBlocks: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f(&protoCfg)
|
f(&cfg)
|
||||||
}
|
}
|
||||||
if st == nil {
|
if st == nil {
|
||||||
st = storage.NewMemoryStore()
|
st = storage.NewMemoryStore()
|
||||||
}
|
}
|
||||||
log := zaptest.NewLogger(t)
|
log := zaptest.NewLogger(t)
|
||||||
bc, err := core.NewBlockchain(st, protoCfg, log)
|
bc, err := core.NewBlockchain(st, cfg, log)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if run {
|
if run {
|
||||||
go bc.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
|
// NewMultiWithCustomConfig is similar to NewMulti, except it allows to override the
|
||||||
// default configuration.
|
// 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)
|
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
|
// Run method is called on the Blockchain instance. If not, it is its caller's
|
||||||
// responsibility to do that before using the chain and
|
// responsibility to do that before using the chain and
|
||||||
// to properly Close the chain when done.
|
// 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)
|
bc, validator, committee, err := NewMultiWithCustomConfigAndStoreNoCheck(t, f, st)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
if run {
|
if run {
|
||||||
|
@ -193,24 +198,28 @@ func NewMultiWithCustomConfigAndStore(t testing.TB, f func(*config.ProtocolConfi
|
||||||
|
|
||||||
// NewMultiWithCustomConfigAndStoreNoCheck is similar to NewMultiWithCustomConfig,
|
// NewMultiWithCustomConfigAndStoreNoCheck is similar to NewMultiWithCustomConfig,
|
||||||
// but do not perform Blockchain run and do not check Blockchain constructor error.
|
// 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) {
|
func NewMultiWithCustomConfigAndStoreNoCheck(t testing.TB, f func(*config.Blockchain), st storage.Store) (*core.Blockchain, neotest.Signer, neotest.Signer, error) {
|
||||||
protoCfg := config.ProtocolConfiguration{
|
var cfg = config.Blockchain{
|
||||||
Magic: netmode.UnitTestNet,
|
ProtocolConfiguration: config.ProtocolConfiguration{
|
||||||
MaxTraceableBlocks: MaxTraceableBlocks,
|
Magic: netmode.UnitTestNet,
|
||||||
TimePerBlock: TimePerBlock,
|
MaxTraceableBlocks: MaxTraceableBlocks,
|
||||||
StandbyCommittee: standByCommittee,
|
TimePerBlock: TimePerBlock,
|
||||||
ValidatorsCount: 4,
|
StandbyCommittee: standByCommittee,
|
||||||
VerifyBlocks: true,
|
ValidatorsCount: 4,
|
||||||
VerifyTransactions: true,
|
VerifyTransactions: true,
|
||||||
|
},
|
||||||
|
Ledger: config.Ledger{
|
||||||
|
VerifyBlocks: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if f != nil {
|
if f != nil {
|
||||||
f(&protoCfg)
|
f(&cfg)
|
||||||
}
|
}
|
||||||
if st == nil {
|
if st == nil {
|
||||||
st = storage.NewMemoryStore()
|
st = storage.NewMemoryStore()
|
||||||
}
|
}
|
||||||
|
|
||||||
log := zaptest.NewLogger(t)
|
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
|
return bc, neotest.NewMultiSigner(multiValidatorAcc...), neotest.NewMultiSigner(multiCommitteeAcc...), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,7 +207,7 @@ func newTestServer(t *testing.T, serverConfig ServerConfig) *Server {
|
||||||
return newTestServerWithCustomCfg(t, serverConfig, nil)
|
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 {
|
if len(serverConfig.Addresses) == 0 {
|
||||||
// Normally it will be done by ApplicationConfiguration.GetAddresses().
|
// Normally it will be done by ApplicationConfiguration.GetAddresses().
|
||||||
serverConfig.Addresses = []config.AnnounceableAddress{{Address: ":0"}}
|
serverConfig.Addresses = []config.AnnounceableAddress{{Address: ":0"}}
|
||||||
|
|
|
@ -59,7 +59,7 @@ type (
|
||||||
mempool.Feer
|
mempool.Feer
|
||||||
Blockqueuer
|
Blockqueuer
|
||||||
GetBlock(hash util.Uint256) (*block.Block, error)
|
GetBlock(hash util.Uint256) (*block.Block, error)
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetHeader(hash util.Uint256) (*block.Header, error)
|
GetHeader(hash util.Uint256) (*block.Header, error)
|
||||||
GetHeaderHash(uint32) util.Uint256
|
GetHeaderHash(uint32) util.Uint256
|
||||||
GetMaxVerificationGAS() int64
|
GetMaxVerificationGAS() int64
|
||||||
|
@ -177,7 +177,7 @@ func newServerFromConstructors(config ServerConfig, chain Ledger, stSync StateSy
|
||||||
ServerConfig: config,
|
ServerConfig: config,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
id: randomID(),
|
id: randomID(),
|
||||||
config: chain.GetConfig(),
|
config: chain.GetConfig().ProtocolConfiguration,
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
relayFin: make(chan struct{}),
|
relayFin: make(chan struct{}),
|
||||||
register: make(chan Peer),
|
register: make(chan Peer),
|
||||||
|
|
|
@ -56,10 +56,11 @@ func (f *fakeConsensus) OnTransaction(tx *transaction.Transaction) {
|
||||||
func (f *fakeConsensus) GetPayload(h util.Uint256) *payload.Extensible { panic("implement me") }
|
func (f *fakeConsensus) GetPayload(h util.Uint256) *payload.Extensible { panic("implement me") }
|
||||||
|
|
||||||
func TestNewServer(t *testing.T) {
|
func TestNewServer(t *testing.T) {
|
||||||
bc := &fakechain.FakeChain{ProtocolConfiguration: config.ProtocolConfiguration{
|
bc := &fakechain.FakeChain{Blockchain: config.Blockchain{
|
||||||
P2PStateExchangeExtensions: true,
|
ProtocolConfiguration: config.ProtocolConfiguration{
|
||||||
StateRootInHeader: true,
|
P2PStateExchangeExtensions: true,
|
||||||
}}
|
StateRootInHeader: true,
|
||||||
|
}}}
|
||||||
s, err := newServerFromConstructors(ServerConfig{}, bc, new(fakechain.FakeStateSync), nil, newFakeTransp, newTestDiscovery)
|
s, err := newServerFromConstructors(ServerConfig{}, bc, new(fakechain.FakeStateSync), nil, newFakeTransp, newTestDiscovery)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
|
@ -387,7 +388,7 @@ func (s *Server) testHandleMessage(t *testing.T, p Peer, cmd CommandType, pl pay
|
||||||
return s
|
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
|
var s *Server
|
||||||
srvCfg := ServerConfig{UserAgent: "/test/"}
|
srvCfg := ServerConfig{UserAgent: "/test/"}
|
||||||
if protocolCfg != nil {
|
if protocolCfg != nil {
|
||||||
|
@ -820,15 +821,15 @@ func TestHandleGetMPTData(t *testing.T) {
|
||||||
require.Eventually(t, recvResponse.Load, time.Second, time.Millisecond)
|
require.Eventually(t, recvResponse.Load, time.Second, time.Millisecond)
|
||||||
}
|
}
|
||||||
t.Run("KeepOnlyLatestState on", func(t *testing.T) {
|
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.P2PStateExchangeExtensions = true
|
||||||
c.KeepOnlyLatestState = true
|
c.Ledger.KeepOnlyLatestState = true
|
||||||
})
|
})
|
||||||
check(t, s)
|
check(t, s)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("good", func(t *testing.T) {
|
t.Run("good", func(t *testing.T) {
|
||||||
s := startTestServer(t, func(c *config.ProtocolConfiguration) {
|
s := startTestServer(t, func(c *config.Blockchain) {
|
||||||
c.P2PStateExchangeExtensions = true
|
c.P2PStateExchangeExtensions = true
|
||||||
})
|
})
|
||||||
check(t, s)
|
check(t, s)
|
||||||
|
|
|
@ -70,7 +70,7 @@ func dupNotaryRequest(t *testing.T, p *payload.P2PNotaryRequest) *payload.P2PNot
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotary(t *testing.T) {
|
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
|
c.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, validators, committee)
|
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
|
|
@ -27,7 +27,7 @@ type (
|
||||||
BlockHeight() uint32
|
BlockHeight() uint32
|
||||||
FeePerByte() int64
|
FeePerByte() int64
|
||||||
GetBaseExecFee() int64
|
GetBaseExecFee() int64
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetMaxVerificationGAS() int64
|
GetMaxVerificationGAS() int64
|
||||||
GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) (*interop.Context, error)
|
GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) (*interop.Context, error)
|
||||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||||
|
|
|
@ -72,7 +72,7 @@ type (
|
||||||
GetBaseExecFee() int64
|
GetBaseExecFee() int64
|
||||||
GetBlock(hash util.Uint256) (*block.Block, error)
|
GetBlock(hash util.Uint256) (*block.Block, error)
|
||||||
GetCommittee() (keys.PublicKeys, error)
|
GetCommittee() (keys.PublicKeys, error)
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
GetContractScriptHash(id int32) (util.Uint160, error)
|
GetContractScriptHash(id int32) (util.Uint160, error)
|
||||||
GetContractState(hash util.Uint160) *state.Contract
|
GetContractState(hash util.Uint160) *state.Contract
|
||||||
GetEnrollments() ([]state.Validator, error)
|
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.SessionEnabled {
|
||||||
if conf.SessionExpirationTime <= 0 {
|
if conf.SessionExpirationTime <= 0 {
|
||||||
conf.SessionExpirationTime = int(protoCfg.TimePerBlock / time.Second)
|
conf.SessionExpirationTime = int(protoCfg.TimePerBlock / time.Second)
|
||||||
|
@ -935,7 +935,7 @@ contract_loop:
|
||||||
lub, ok := lastUpdated[cs.ID]
|
lub, ok := lastUpdated[cs.ID]
|
||||||
if !ok {
|
if !ok {
|
||||||
cfg := s.chain.GetConfig()
|
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()))
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get LastUpdatedBlock for balance of %s token: internal database inconsistency", cs.Hash.StringLE()))
|
||||||
}
|
}
|
||||||
lub = stateSyncPoint
|
lub = stateSyncPoint
|
||||||
|
@ -1057,7 +1057,7 @@ func (s *Server) getNEP17Balances(ps params.Params) (interface{}, *neorpc.Error)
|
||||||
lub, ok := lastUpdated[cs.ID]
|
lub, ok := lastUpdated[cs.ID]
|
||||||
if !ok {
|
if !ok {
|
||||||
cfg := s.chain.GetConfig()
|
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()))
|
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get LastUpdatedBlock for balance of %s token: internal database inconsistency", cs.Hash.StringLE()))
|
||||||
}
|
}
|
||||||
lub = stateSyncPoint
|
lub = stateSyncPoint
|
||||||
|
@ -1396,7 +1396,7 @@ func makeStorageKey(id int32, key []byte) []byte {
|
||||||
var errKeepOnlyLatestState = errors.New("'KeepOnlyLatestState' setting is enabled")
|
var errKeepOnlyLatestState = errors.New("'KeepOnlyLatestState' setting is enabled")
|
||||||
|
|
||||||
func (s *Server) getProof(ps params.Params) (interface{}, *neorpc.Error) {
|
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))
|
return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'getproof' is not supported: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
root, err := ps.Value(0).GetUint256()
|
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) {
|
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))
|
return nil, neorpc.NewInvalidRequestError(fmt.Sprintf("'verifyproof' is not supported: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
root, err := ps.Value(0).GetUint256()
|
root, err := ps.Value(0).GetUint256()
|
||||||
|
@ -1455,7 +1455,7 @@ func (s *Server) getState(ps params.Params) (interface{}, *neorpc.Error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot")
|
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())
|
curr, err := s.chain.GetStateModule().GetStateRoot(s.chain.BlockHeight())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err))
|
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 {
|
if err != nil {
|
||||||
return nil, neorpc.WrapErrorWithData(neorpc.ErrInvalidParams, "invalid stateroot")
|
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())
|
curr, err := s.chain.GetStateModule().GetStateRoot(s.chain.BlockHeight())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, neorpc.NewInternalServerError(fmt.Sprintf("failed to get current stateroot: %s", err))
|
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
|
// specified stateroot is stored at the specified height for further request
|
||||||
// handling consistency.
|
// handling consistency.
|
||||||
func (s *Server) getHistoricParams(reqParams params.Params) (uint32, *neorpc.Error) {
|
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))
|
return 0, neorpc.NewInvalidRequestError(fmt.Sprintf("only latest state is supported: %s", errKeepOnlyLatestState))
|
||||||
}
|
}
|
||||||
if len(reqParams) < 1 {
|
if len(reqParams) < 1 {
|
||||||
|
|
|
@ -67,7 +67,7 @@ func getUnitTestChainWithCustomConfig(t testing.TB, enableOracle bool, enableNot
|
||||||
|
|
||||||
memoryStore := storage.NewMemoryStore()
|
memoryStore := storage.NewMemoryStore()
|
||||||
logger := zaptest.NewLogger(t)
|
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")
|
require.NoError(t, err, "could not create chain")
|
||||||
|
|
||||||
var orc *oracle.Oracle
|
var orc *oracle.Oracle
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
type (
|
type (
|
||||||
// Ledger is an interface to Blockchain sufficient for Service.
|
// Ledger is an interface to Blockchain sufficient for Service.
|
||||||
Ledger interface {
|
Ledger interface {
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.Blockchain
|
||||||
HeaderHeight() uint32
|
HeaderHeight() uint32
|
||||||
SubscribeForBlocks(ch chan *block.Block)
|
SubscribeForBlocks(ch chan *block.Block)
|
||||||
UnsubscribeFromBlocks(ch chan *block.Block)
|
UnsubscribeFromBlocks(ch chan *block.Block)
|
||||||
|
|
|
@ -298,7 +298,7 @@ func checkVoteBroadcasted(t *testing.T, bc *core.Blockchain, p *payload.Extensib
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStateroot_GetLatestStateHeight(t *testing.T) {
|
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
|
c.P2PSigExtensions = true
|
||||||
})
|
})
|
||||||
e := neotest.NewExecutor(t, bc, validators, committee)
|
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
|
|
@ -132,14 +132,14 @@ func newChain() (*core.Blockchain, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
unitTestNetCfg.ProtocolConfiguration.VerifyBlocks = false
|
unitTestNetCfg.ApplicationConfiguration.VerifyBlocks = false
|
||||||
zapCfg := zap.NewDevelopmentConfig()
|
zapCfg := zap.NewDevelopmentConfig()
|
||||||
zapCfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel)
|
zapCfg.Level = zap.NewAtomicLevelAt(zapcore.InfoLevel)
|
||||||
log, err := zapCfg.Build()
|
log, err := zapCfg.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.ProtocolConfiguration, log)
|
chain, err := core.NewBlockchain(storage.NewMemoryStore(), unitTestNetCfg.Blockchain(), log)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue