Merge pull request #3212 from nspcc-dev/drop-history
Move NativeUpdateHistory logic uner hardforks
This commit is contained in:
commit
ff958706f4
34 changed files with 170 additions and 306 deletions
|
@ -26,17 +26,6 @@ ProtocolConfiguration:
|
||||||
Hardforks:
|
Hardforks:
|
||||||
Aspidochelone: 3000000
|
Aspidochelone: 3000000
|
||||||
Basilisk: 4500000
|
Basilisk: 4500000
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
Notary: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -38,16 +38,6 @@ ProtocolConfiguration:
|
||||||
Hardforks:
|
Hardforks:
|
||||||
Aspidochelone: 1730000
|
Aspidochelone: 1730000
|
||||||
Basilisk: 4120000
|
Basilisk: 4120000
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -16,16 +16,6 @@ ProtocolConfiguration:
|
||||||
- node_four:20336
|
- node_four:20336
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: false
|
P2PSigExtensions: false
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -16,16 +16,6 @@ ProtocolConfiguration:
|
||||||
- node_four:20336
|
- node_four:20336
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: false
|
P2PSigExtensions: false
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -10,16 +10,6 @@ ProtocolConfiguration:
|
||||||
- node_single:20333
|
- node_single:20333
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: false
|
P2PSigExtensions: false
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -16,16 +16,6 @@ ProtocolConfiguration:
|
||||||
- node_four:20336
|
- node_four:20336
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: false
|
P2PSigExtensions: false
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -16,16 +16,6 @@ ProtocolConfiguration:
|
||||||
- node_four:20336
|
- node_four:20336
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: false
|
P2PSigExtensions: false
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -16,16 +16,6 @@ ProtocolConfiguration:
|
||||||
- localhost:20336
|
- localhost:20336
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: false
|
P2PSigExtensions: false
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -24,17 +24,6 @@ ProtocolConfiguration:
|
||||||
- morph7.t5.fs.neo.org:50333
|
- morph7.t5.fs.neo.org:50333
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: true
|
P2PSigExtensions: true
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
Notary: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -41,16 +41,6 @@ ProtocolConfiguration:
|
||||||
Hardforks:
|
Hardforks:
|
||||||
Aspidochelone: 210000
|
Aspidochelone: 210000
|
||||||
Basilisk: 2680000
|
Basilisk: 2680000
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
|
|
||||||
ApplicationConfiguration:
|
ApplicationConfiguration:
|
||||||
SkipBlockVerification: false
|
SkipBlockVerification: false
|
||||||
|
|
|
@ -8,17 +8,6 @@ ProtocolConfiguration:
|
||||||
ValidatorsCount: 1
|
ValidatorsCount: 1
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: true
|
P2PSigExtensions: true
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
Notary: [0]
|
|
||||||
Hardforks:
|
Hardforks:
|
||||||
Aspidochelone: 25
|
Aspidochelone: 25
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,6 @@ ProtocolConfiguration:
|
||||||
- 127.0.0.1:20336
|
- 127.0.0.1:20336
|
||||||
VerifyTransactions: true
|
VerifyTransactions: true
|
||||||
P2PSigExtensions: true
|
P2PSigExtensions: true
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
Notary: [0]
|
|
||||||
Hardforks:
|
Hardforks:
|
||||||
Aspidochelone: 25
|
Aspidochelone: 25
|
||||||
|
|
||||||
|
|
|
@ -334,7 +334,6 @@ protocol-related settings described in the table below.
|
||||||
| MaxTransactionsPerBlock | `uint16` | `512` | Maximum number of transactions per block. |
|
| MaxTransactionsPerBlock | `uint16` | `512` | Maximum number of transactions per block. |
|
||||||
| MaxValidUntilBlockIncrement | `uint32` | `5760` | Upper height increment limit for transaction's ValidUntilBlock field value relative to the current blockchain height, exceeding which a transaction will fail validation. It is set to estimated daily number of blocks with 15s interval by default. |
|
| MaxValidUntilBlockIncrement | `uint32` | `5760` | Upper height increment limit for transaction's ValidUntilBlock field value relative to the current blockchain height, exceeding which a transaction will fail validation. It is set to estimated daily number of blocks with 15s interval by default. |
|
||||||
| MemPoolSize | `int` | `50000` | Size of the node's memory pool where transactions are stored before they are added to block. |
|
| MemPoolSize | `int` | `50000` | Size of the node's memory pool where transactions are stored before they are added to block. |
|
||||||
| NativeActivations | `map[string][]uint32` | ContractManagement: [0]<br>StdLib: [0]<br>CryptoLib: [0]<br>LedgerContract: [0]<br>NeoToken: [0]<br>GasToken: [0]<br>PolicyContract: [0]<br>RoleManagement: [0]<br>OracleContract: [0] | The list of histories of native contracts updates. Each list item shod be presented as a known native contract name with the corresponding list of chain's heights. The contract is not active until chain reaches the first height value specified in the list. | `Notary` is supported. |
|
|
||||||
| 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 attribute `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 attribute `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`). |
|
||||||
|
@ -383,9 +382,9 @@ where:
|
||||||
|
|
||||||
Note that Roles is a NeoGo extension that isn't supported by the NeoC# node and
|
Note that Roles is a NeoGo extension that isn't supported by the NeoC# node and
|
||||||
must be disabled on the public Neo N3 networks. Roles extension is compatible
|
must be disabled on the public Neo N3 networks. Roles extension is compatible
|
||||||
with NativeUpdateHistory setting, which means that specified roles will be set
|
with Hardforks setting, which means that specified roles will be set
|
||||||
only during native RoleManagement contract initialisation (which may be
|
only during native RoleManagement contract initialisation (which may be
|
||||||
performed in some non-genesis block). By default, no roles are designated.
|
performed in some non-genesis hardfork). By default, no roles are designated.
|
||||||
|
|
||||||
- `Transaction` is a container for transaction script that should be deployed in
|
- `Transaction` is a container for transaction script that should be deployed in
|
||||||
the genesis block if provided. `Transaction` includes `Script` which is a
|
the genesis block if provided. `Transaction` includes `Script` which is a
|
||||||
|
|
|
@ -171,9 +171,8 @@ verify and broadcast `P2PNotaryRequest` P2P payloads, properly initialize native
|
||||||
Notary contract and designate `P2PNotary` node role in RoleManagement native
|
Notary contract and designate `P2PNotary` node role in RoleManagement native
|
||||||
contract.
|
contract.
|
||||||
|
|
||||||
If you use custom `NativeActivations` subsection of the `ProtocolConfiguration`
|
Currently, Notary contract activation height is not configurable and is always
|
||||||
section in your node config, specify the height of the Notary contract
|
set to 0 (if `P2PSigExtensions` are enabled).
|
||||||
activation, e.g. `0`.
|
|
||||||
|
|
||||||
Note, that even if `P2PSigExtensions` config subsection enables notary-related
|
Note, that even if `P2PSigExtensions` config subsection enables notary-related
|
||||||
logic in the network, it still does not turn your node into notary service node.
|
logic in the network, it still does not turn your node into notary service node.
|
||||||
|
@ -184,17 +183,6 @@ To enable notary service node functionality refer to the
|
||||||
|
|
||||||
```
|
```
|
||||||
P2PSigExtensions: true
|
P2PSigExtensions: true
|
||||||
NativeActivations:
|
|
||||||
Notary: [0]
|
|
||||||
ContractManagement: [0]
|
|
||||||
StdLib: [0]
|
|
||||||
CryptoLib: [0]
|
|
||||||
LedgerContract: [0]
|
|
||||||
NeoToken: [0]
|
|
||||||
GasToken: [0]
|
|
||||||
PolicyContract: [0]
|
|
||||||
RoleManagement: [0]
|
|
||||||
OracleContract: [0]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -44,8 +43,6 @@ type (
|
||||||
// exceeding that a transaction should fail validation. It is set to estimated daily number
|
// exceeding that a transaction should fail validation. It is set to estimated daily number
|
||||||
// of blocks with 15s interval.
|
// of blocks with 15s interval.
|
||||||
MaxValidUntilBlockIncrement uint32 `yaml:"MaxValidUntilBlockIncrement"`
|
MaxValidUntilBlockIncrement uint32 `yaml:"MaxValidUntilBlockIncrement"`
|
||||||
// NativeUpdateHistories is a list of histories of native contracts updates.
|
|
||||||
NativeUpdateHistories map[string][]uint32 `yaml:"NativeActivations"`
|
|
||||||
// P2PSigExtensions enables additional signature-related logic.
|
// P2PSigExtensions enables additional signature-related logic.
|
||||||
P2PSigExtensions bool `yaml:"P2PSigExtensions"`
|
P2PSigExtensions bool `yaml:"P2PSigExtensions"`
|
||||||
// P2PStateExchangeExtensions enables additional P2P MPT state data exchange logic.
|
// P2PStateExchangeExtensions enables additional P2P MPT state data exchange logic.
|
||||||
|
@ -86,11 +83,6 @@ func (p *ProtocolConfiguration) Validate() error {
|
||||||
if p.TimePerBlock%time.Millisecond != 0 {
|
if p.TimePerBlock%time.Millisecond != 0 {
|
||||||
return errors.New("TimePerBlock must be an integer number of milliseconds")
|
return errors.New("TimePerBlock must be an integer number of milliseconds")
|
||||||
}
|
}
|
||||||
for name := range p.NativeUpdateHistories {
|
|
||||||
if !nativenames.IsValid(name) {
|
|
||||||
return fmt.Errorf("NativeActivations configuration section contains unexpected native contract name: %s", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for name := range p.Hardforks {
|
for name := range p.Hardforks {
|
||||||
if !IsHardforkValid(name) {
|
if !IsHardforkValid(name) {
|
||||||
return fmt.Errorf("Hardforks configuration section contains unexpected hardfork: %s", name)
|
return fmt.Errorf("Hardforks configuration section contains unexpected hardfork: %s", name)
|
||||||
|
@ -237,7 +229,6 @@ func (p *ProtocolConfiguration) Equals(o *ProtocolConfiguration) bool {
|
||||||
p.VerifyTransactions != o.VerifyTransactions ||
|
p.VerifyTransactions != o.VerifyTransactions ||
|
||||||
len(p.CommitteeHistory) != len(o.CommitteeHistory) ||
|
len(p.CommitteeHistory) != len(o.CommitteeHistory) ||
|
||||||
len(p.Hardforks) != len(o.Hardforks) ||
|
len(p.Hardforks) != len(o.Hardforks) ||
|
||||||
len(p.NativeUpdateHistories) != len(o.NativeUpdateHistories) ||
|
|
||||||
len(p.SeedList) != len(o.SeedList) ||
|
len(p.SeedList) != len(o.SeedList) ||
|
||||||
len(p.StandbyCommittee) != len(o.StandbyCommittee) ||
|
len(p.StandbyCommittee) != len(o.StandbyCommittee) ||
|
||||||
len(p.ValidatorsHistory) != len(o.ValidatorsHistory) {
|
len(p.ValidatorsHistory) != len(o.ValidatorsHistory) {
|
||||||
|
@ -255,17 +246,6 @@ func (p *ProtocolConfiguration) Equals(o *ProtocolConfiguration) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for k, v := range p.NativeUpdateHistories {
|
|
||||||
vo := o.NativeUpdateHistories[k]
|
|
||||||
if len(v) != len(vo) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for i := range v {
|
|
||||||
if v[i] != vo[i] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := range p.SeedList {
|
for i := range p.SeedList {
|
||||||
if p.SeedList[i] != o.SeedList[i] {
|
if p.SeedList[i] != o.SeedList[i] {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -28,12 +28,6 @@ func TestProtocolConfigurationValidation(t *testing.T) {
|
||||||
ValidatorsCount: 1,
|
ValidatorsCount: 1,
|
||||||
}
|
}
|
||||||
require.Error(t, p.Validate())
|
require.Error(t, p.Validate())
|
||||||
p = &ProtocolConfiguration{
|
|
||||||
NativeUpdateHistories: map[string][]uint32{
|
|
||||||
"someContract": {0, 10},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
require.Error(t, p.Validate())
|
|
||||||
p = &ProtocolConfiguration{
|
p = &ProtocolConfiguration{
|
||||||
StandbyCommittee: []string{
|
StandbyCommittee: []string{
|
||||||
"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2",
|
"02b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2",
|
||||||
|
@ -247,17 +241,6 @@ func TestProtocolConfigurationEquals(t *testing.T) {
|
||||||
p.Hardforks = nil
|
p.Hardforks = nil
|
||||||
o.Hardforks = nil
|
o.Hardforks = nil
|
||||||
|
|
||||||
p.NativeUpdateHistories = map[string][]uint32{"Contract": {1, 2, 3}}
|
|
||||||
o.NativeUpdateHistories = map[string][]uint32{"Contract": {1, 2, 3}}
|
|
||||||
require.True(t, p.Equals(o))
|
|
||||||
p.NativeUpdateHistories["Contract"] = []uint32{1, 2, 3, 4}
|
|
||||||
require.False(t, p.Equals(o))
|
|
||||||
p.NativeUpdateHistories["Contract"] = []uint32{1, 2, 4}
|
|
||||||
require.False(t, p.Equals(o))
|
|
||||||
|
|
||||||
p.NativeUpdateHistories = nil
|
|
||||||
o.NativeUpdateHistories = nil
|
|
||||||
|
|
||||||
p.SeedList = []string{"url1", "url2"}
|
p.SeedList = []string{"url1", "url2"}
|
||||||
o.SeedList = []string{"url1", "url2"}
|
o.SeedList = []string{"url1", "url2"}
|
||||||
require.True(t, p.Equals(o))
|
require.True(t, p.Equals(o))
|
||||||
|
|
4
pkg/config/testdata/protocol.test.yml
vendored
4
pkg/config/testdata/protocol.test.yml
vendored
|
@ -1,4 +0,0 @@
|
||||||
ProtocolConfiguration:
|
|
||||||
NativeActivations:
|
|
||||||
ContractManagement: [0]
|
|
||||||
UnexpectedContractName: [0]
|
|
|
@ -283,10 +283,6 @@ func NewBlockchain(s storage.Store, cfg config.Blockchain, log *zap.Logger) (*Bl
|
||||||
zap.Int("StateSyncInterval", cfg.StateSyncInterval))
|
zap.Int("StateSyncInterval", cfg.StateSyncInterval))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(cfg.NativeUpdateHistories) == 0 {
|
|
||||||
cfg.NativeUpdateHistories = map[string][]uint32{}
|
|
||||||
log.Info("NativeActivations are not set, using default values")
|
|
||||||
}
|
|
||||||
if cfg.Hardforks == nil {
|
if cfg.Hardforks == nil {
|
||||||
cfg.Hardforks = map[string]uint32{}
|
cfg.Hardforks = map[string]uint32{}
|
||||||
for _, hf := range config.Hardforks {
|
for _, hf := range config.Hardforks {
|
||||||
|
@ -485,8 +481,8 @@ func (bc *Blockchain) init() error {
|
||||||
for _, c := range bc.contracts.Contracts {
|
for _, c := range bc.contracts.Contracts {
|
||||||
md := c.Metadata()
|
md := c.Metadata()
|
||||||
storedCS := bc.GetContractState(md.Hash)
|
storedCS := bc.GetContractState(md.Hash)
|
||||||
history := md.UpdateHistory
|
// Check that contract was deployed.
|
||||||
if len(history) == 0 || history[0] > bHeight {
|
if !bc.isHardforkEnabled(c.ActiveIn(), bHeight) {
|
||||||
if storedCS != nil {
|
if storedCS != nil {
|
||||||
return fmt.Errorf("native contract %s is already stored, but marked as inactive for height %d in config", md.Name, bHeight)
|
return fmt.Errorf("native contract %s is already stored, but marked as inactive for height %d in config", md.Name, bHeight)
|
||||||
}
|
}
|
||||||
|
@ -1022,19 +1018,31 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage)
|
||||||
|
|
||||||
func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error {
|
func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error {
|
||||||
for _, c := range bc.contracts.Contracts {
|
for _, c := range bc.contracts.Contracts {
|
||||||
for _, h := range c.Metadata().UpdateHistory {
|
// Check that contract was deployed.
|
||||||
if blockHeight >= h { // check that contract was deployed.
|
if !bc.isHardforkEnabled(c.ActiveIn(), blockHeight) {
|
||||||
err := c.InitializeCache(blockHeight, d)
|
continue
|
||||||
if err != nil {
|
}
|
||||||
return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err)
|
err := c.InitializeCache(blockHeight, d)
|
||||||
}
|
if err != nil {
|
||||||
break
|
return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isHardforkEnabled returns true if the specified hardfork is enabled at the
|
||||||
|
// given height. nil hardfork is treated as always enabled.
|
||||||
|
func (bc *Blockchain) isHardforkEnabled(hf *config.Hardfork, blockHeight uint32) bool {
|
||||||
|
hfs := bc.config.Hardforks
|
||||||
|
if hf != nil {
|
||||||
|
start, ok := hfs[hf.String()]
|
||||||
|
if !ok || start < blockHeight {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Run runs chain loop, it needs to be run as goroutine and executing it is
|
// Run runs chain loop, it needs to be run as goroutine and executing it is
|
||||||
// critical for correct Blockchain operation.
|
// critical for correct Blockchain operation.
|
||||||
func (bc *Blockchain) Run() {
|
func (bc *Blockchain) Run() {
|
||||||
|
@ -3008,8 +3016,8 @@ func (bc *Blockchain) GetMaxNotValidBeforeDelta() (uint32, error) {
|
||||||
if !bc.config.P2PSigExtensions {
|
if !bc.config.P2PSigExtensions {
|
||||||
panic("disallowed call to Notary") // critical error, thus panic.
|
panic("disallowed call to Notary") // critical error, thus panic.
|
||||||
}
|
}
|
||||||
if bc.contracts.Notary.Metadata().UpdateHistory[0] > bc.BlockHeight() {
|
if !bc.isHardforkEnabled(bc.contracts.Notary.ActiveIn(), bc.BlockHeight()) {
|
||||||
return 0, fmt.Errorf("native Notary is active starting from %d", bc.contracts.Notary.Metadata().UpdateHistory[0])
|
return 0, fmt.Errorf("native Notary is active starting from %s", bc.contracts.Notary.ActiveIn().String())
|
||||||
}
|
}
|
||||||
return bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao), nil
|
return bc.contracts.Notary.GetMaxNotValidBeforeDelta(bc.dao), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,26 +237,6 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
require.True(t, strings.Contains(err.Error(), "can't init cache for Management native contract"), err)
|
require.True(t, strings.Contains(err.Error(), "can't init cache for Management native contract"), err)
|
||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
t.Run("invalid native contract deactivation", func(t *testing.T) {
|
|
||||||
ps = newPS(t)
|
|
||||||
_, _, _, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, func(c *config.Blockchain) {
|
|
||||||
customConfig(c)
|
|
||||||
c.NativeUpdateHistories = map[string][]uint32{
|
|
||||||
nativenames.Policy: {0},
|
|
||||||
nativenames.Neo: {0},
|
|
||||||
nativenames.Gas: {0},
|
|
||||||
nativenames.Designation: {0},
|
|
||||||
nativenames.StdLib: {0},
|
|
||||||
nativenames.Management: {0},
|
|
||||||
nativenames.Oracle: {0},
|
|
||||||
nativenames.Ledger: {0},
|
|
||||||
nativenames.Notary: {0},
|
|
||||||
nativenames.CryptoLib: {h + 10},
|
|
||||||
}
|
|
||||||
}, ps)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("native contract %s is already stored, but marked as inactive for height %d in config", nativenames.CryptoLib, h)), err)
|
|
||||||
})
|
|
||||||
t.Run("invalid native contract activation", func(t *testing.T) {
|
t.Run("invalid native contract activation", func(t *testing.T) {
|
||||||
ps = newPS(t)
|
ps = newPS(t)
|
||||||
|
|
||||||
|
@ -339,6 +319,7 @@ func TestBlockchain_InitializeNeoCache_Bug3181(t *testing.T) {
|
||||||
|
|
||||||
// This test enables Notary native contract at non-zero height and checks that no
|
// This test enables Notary native contract at non-zero height and checks that no
|
||||||
// Notary cache initialization is performed before that height on node restart.
|
// Notary cache initialization is performed before that height on node restart.
|
||||||
|
/*
|
||||||
func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) {
|
func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) {
|
||||||
const notaryEnabledHeight = 3
|
const notaryEnabledHeight = 3
|
||||||
ps, path := newLevelDBForTestingWithPath(t, "")
|
ps, path := newLevelDBForTestingWithPath(t, "")
|
||||||
|
@ -399,6 +380,7 @@ func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) {
|
||||||
_, err = e.Chain.GetMaxNotValidBeforeDelta()
|
_, err = e.Chain.GetMaxNotValidBeforeDelta()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func TestBlockchain_AddHeaders(t *testing.T) {
|
func TestBlockchain_AddHeaders(t *testing.T) {
|
||||||
bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
|
bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
|
||||||
|
@ -1116,25 +1098,13 @@ func TestBlockchain_MPTDeleteNoKey(t *testing.T) {
|
||||||
cValidatorInvoker.Invoke(t, stackitem.Null{}, "delValue", "non-existent-key")
|
cValidatorInvoker.Invoke(t, stackitem.Null{}, "delValue", "non-existent-key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that UpdateHistory is added to ProtocolConfiguration for all native contracts
|
// Test that all default configurations are loadable.
|
||||||
// for all default configurations. If UpdateHistory is not added to config, then
|
func TestConfig_LoadDefaultConfigs(t *testing.T) {
|
||||||
// native contract is disabled. It's easy to forget about config while adding new
|
|
||||||
// native contract.
|
|
||||||
func TestConfigNativeUpdateHistory(t *testing.T) {
|
|
||||||
var prefixPath = filepath.Join("..", "..", "config")
|
var prefixPath = filepath.Join("..", "..", "config")
|
||||||
check := func(t *testing.T, cfgFileSuffix any) {
|
check := func(t *testing.T, cfgFileSuffix any) {
|
||||||
cfgPath := filepath.Join(prefixPath, fmt.Sprintf("protocol.%s.yml", cfgFileSuffix))
|
cfgPath := filepath.Join(prefixPath, fmt.Sprintf("protocol.%s.yml", cfgFileSuffix))
|
||||||
cfg, err := config.LoadFile(cfgPath)
|
_, err := config.LoadFile(cfgPath)
|
||||||
require.NoError(t, err, fmt.Errorf("failed to load %s", cfgPath))
|
require.NoError(t, err, fmt.Errorf("failed to load %s", cfgPath))
|
||||||
natives := native.NewContracts(cfg.ProtocolConfiguration)
|
|
||||||
assert.Equal(t, len(natives.Contracts),
|
|
||||||
len(cfg.ProtocolConfiguration.NativeUpdateHistories),
|
|
||||||
fmt.Errorf("protocol configuration file %s: extra or missing NativeUpdateHistory in NativeActivations section", cfgPath))
|
|
||||||
for _, c := range natives.Contracts {
|
|
||||||
assert.NotNil(t, cfg.ProtocolConfiguration.NativeUpdateHistories[c.Metadata().Name],
|
|
||||||
fmt.Errorf("protocol configuration file %s: configuration for %s native contract is missing in NativeActivations section; "+
|
|
||||||
"edit the test if the contract should be disabled", cfgPath, c.Metadata().Name))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
testCases := []any{
|
testCases := []any{
|
||||||
netmode.MainNet,
|
netmode.MainNet,
|
||||||
|
|
|
@ -153,6 +153,9 @@ type MethodAndPrice struct {
|
||||||
// Contract is an interface for all native contracts.
|
// Contract is an interface for all native contracts.
|
||||||
type Contract interface {
|
type Contract interface {
|
||||||
Initialize(*Context) error
|
Initialize(*Context) error
|
||||||
|
// ActiveIn returns the hardfork native contract is active from or nil in case
|
||||||
|
// it's always active.
|
||||||
|
ActiveIn() *config.Hardfork
|
||||||
// InitializeCache aimed to initialize contract's cache when the contract has
|
// InitializeCache aimed to initialize contract's cache when the contract has
|
||||||
// been deployed, but in-memory cached data were lost due to the node reset.
|
// been deployed, but in-memory cached data were lost due to the node reset.
|
||||||
// It should be called each time after node restart iff the contract was
|
// It should be called each time after node restart iff the contract was
|
||||||
|
@ -269,12 +272,6 @@ func (c *ContractMD) AddEvent(name string, ps ...manifest.Parameter) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsActive returns true if the contract was deployed by the specified height.
|
|
||||||
func (c *ContractMD) IsActive(height uint32) bool {
|
|
||||||
history := c.UpdateHistory
|
|
||||||
return len(history) != 0 && history[0] <= height
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort sorts interop functions by id.
|
// Sort sorts interop functions by id.
|
||||||
func Sort(fs []Function) {
|
func Sort(fs []Function) {
|
||||||
sort.Slice(fs, func(i, j int) bool { return fs[i].ID < fs[j].ID })
|
sort.Slice(fs, func(i, j int) bool { return fs[i].ID < fs[j].ID })
|
||||||
|
@ -411,6 +408,14 @@ func (ic *Context) IsHardforkEnabled(hf config.Hardfork) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsHardforkActivation denotes whether current block height is the height of
|
||||||
|
// specified hardfork activation.
|
||||||
|
func (ic *Context) IsHardforkActivation(hf config.Hardfork) bool {
|
||||||
|
// Completely rely on proper hardforks initialisation made by core.NewBlockchain.
|
||||||
|
height, ok := ic.Hardforks[hf.String()]
|
||||||
|
return ok && ic.Block.Index == height
|
||||||
|
}
|
||||||
|
|
||||||
// AddNotification creates notification event and appends it to the notification list.
|
// AddNotification creates notification event and appends it to the notification list.
|
||||||
func (ic *Context) AddNotification(hash util.Uint160, name string, item *stackitem.Array) {
|
func (ic *Context) AddNotification(hash util.Uint160, name string, item *stackitem.Array) {
|
||||||
ic.Notifications = append(ic.Notifications, state.NotificationEvent{
|
ic.Notifications = append(ic.Notifications, state.NotificationEvent{
|
||||||
|
|
|
@ -110,14 +110,6 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
||||||
cs.Contracts = append(cs.Contracts, notary)
|
cs.Contracts = append(cs.Contracts, notary)
|
||||||
}
|
}
|
||||||
|
|
||||||
setDefaultHistory := len(cfg.NativeUpdateHistories) == 0
|
|
||||||
for _, c := range cs.Contracts {
|
|
||||||
var history = []uint32{0}
|
|
||||||
if !setDefaultHistory {
|
|
||||||
history = cfg.NativeUpdateHistories[c.Metadata().Name]
|
|
||||||
}
|
|
||||||
c.Metadata().NativeContract.UpdateHistory = history
|
|
||||||
}
|
|
||||||
return cs
|
return cs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
|
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
|
||||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
@ -308,3 +309,8 @@ func (c *Crypto) OnPersist(ic *interop.Context) error {
|
||||||
func (c *Crypto) PostPersist(ic *interop.Context) error {
|
func (c *Crypto) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (c *Crypto) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||||
|
@ -194,6 +195,11 @@ func (s *Designate) Metadata() *interop.ContractMD {
|
||||||
return &s.ContractMD
|
return &s.ContractMD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (s *Designate) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Designate) getDesignatedByRole(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
func (s *Designate) getDesignatedByRole(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
r, ok := s.getRole(args[0])
|
r, ok := s.getRole(args[0])
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -18,24 +18,30 @@ func Call(ic *interop.Context) error {
|
||||||
if version != 0 {
|
if version != 0 {
|
||||||
return fmt.Errorf("native contract of version %d is not active", version)
|
return fmt.Errorf("native contract of version %d is not active", version)
|
||||||
}
|
}
|
||||||
var meta *interop.ContractMD
|
var (
|
||||||
curr := ic.VM.GetCurrentScriptHash()
|
c interop.Contract
|
||||||
|
curr = ic.VM.GetCurrentScriptHash()
|
||||||
|
)
|
||||||
for _, ctr := range ic.Natives {
|
for _, ctr := range ic.Natives {
|
||||||
m := ctr.Metadata()
|
if ctr.Metadata().Hash == curr {
|
||||||
if m.Hash == curr {
|
c = ctr
|
||||||
meta = m
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if meta == nil {
|
if c == nil {
|
||||||
return fmt.Errorf("native contract %s (version %d) not found", curr.StringLE(), version)
|
return fmt.Errorf("native contract %s (version %d) not found", curr.StringLE(), version)
|
||||||
}
|
}
|
||||||
history := meta.UpdateHistory
|
var (
|
||||||
if len(history) == 0 {
|
meta = c.Metadata()
|
||||||
return fmt.Errorf("native contract %s is disabled", meta.Name)
|
activeIn = c.ActiveIn()
|
||||||
}
|
)
|
||||||
if history[0] > ic.BlockHeight() { // persisting block must not be taken into account.
|
if activeIn != nil {
|
||||||
return fmt.Errorf("native contract %s is active after height = %d", meta.Name, history[0])
|
height, ok := ic.Hardforks[activeIn.String()]
|
||||||
|
// Persisting block must not be taken into account, native contract can be called
|
||||||
|
// only AFTER its initialization block persist, thus, can't use ic.IsHardforkEnabled.
|
||||||
|
if !ok || ic.BlockHeight() < height {
|
||||||
|
return fmt.Errorf("native contract %s is active after hardfork %s", meta.Name, activeIn.String())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m, ok := meta.GetMethodByOffset(ic.VM.Context().IP())
|
m, ok := meta.GetMethodByOffset(ic.VM.Context().IP())
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -76,7 +82,8 @@ func OnPersist(ic *interop.Context) error {
|
||||||
return errors.New("onPersist must be trigered by system")
|
return errors.New("onPersist must be trigered by system")
|
||||||
}
|
}
|
||||||
for _, c := range ic.Natives {
|
for _, c := range ic.Natives {
|
||||||
if !c.Metadata().IsActive(ic.Block.Index) {
|
activeIn := c.ActiveIn()
|
||||||
|
if !(activeIn == nil || ic.IsHardforkEnabled(*activeIn)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := c.OnPersist(ic)
|
err := c.OnPersist(ic)
|
||||||
|
@ -93,7 +100,8 @@ func PostPersist(ic *interop.Context) error {
|
||||||
return errors.New("postPersist must be trigered by system")
|
return errors.New("postPersist must be trigered by system")
|
||||||
}
|
}
|
||||||
for _, c := range ic.Natives {
|
for _, c := range ic.Natives {
|
||||||
if !c.Metadata().IsActive(ic.Block.Index) {
|
activeIn := c.ActiveIn()
|
||||||
|
if !(activeIn == nil || ic.IsHardforkEnabled(*activeIn)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
err := c.PostPersist(ic)
|
err := c.PostPersist(ic)
|
||||||
|
|
|
@ -89,48 +89,50 @@ func TestNativeContract_InvokeInternal(t *testing.T) {
|
||||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("native contract %s (version 0) not found", fakeH.StringLE())), err.Error())
|
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("native contract %s (version 0) not found", fakeH.StringLE())), err.Error())
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("fail, bad NativeUpdateHistory height", func(t *testing.T) {
|
/*
|
||||||
bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) {
|
t.Run("fail, bad NativeUpdateHistory height", func(t *testing.T) {
|
||||||
c.NativeUpdateHistories = map[string][]uint32{
|
bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) {
|
||||||
nativenames.Policy: {0},
|
c.NativeUpdateHistories = map[string][]uint32{
|
||||||
nativenames.Neo: {0},
|
nativenames.Policy: {0},
|
||||||
nativenames.Gas: {0},
|
nativenames.Neo: {0},
|
||||||
nativenames.Designation: {0},
|
nativenames.Gas: {0},
|
||||||
nativenames.StdLib: {0},
|
nativenames.Designation: {0},
|
||||||
nativenames.Management: {0},
|
nativenames.StdLib: {0},
|
||||||
nativenames.Oracle: {0},
|
nativenames.Management: {0},
|
||||||
nativenames.Ledger: {0},
|
nativenames.Oracle: {0},
|
||||||
nativenames.CryptoLib: {1},
|
nativenames.Ledger: {0},
|
||||||
}
|
nativenames.CryptoLib: {1},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
eBad := neotest.NewExecutor(t, bcBad, validatorBad, committeeBad)
|
||||||
|
|
||||||
|
ic, err := bcBad.GetTestVM(trigger.Application, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
v := ic.SpawnVM()
|
||||||
|
v.LoadScriptWithHash(clState.NEF.Script, clState.Hash, callflag.All) // hash is not affected by native update history
|
||||||
|
input := []byte{1, 2, 3, 4}
|
||||||
|
v.Estack().PushVal(input)
|
||||||
|
v.Context().Jump(md.Offset)
|
||||||
|
|
||||||
|
// It's prohibited to call natives before NativeUpdateHistory[0] height.
|
||||||
|
err = v.Run()
|
||||||
|
require.Error(t, err)
|
||||||
|
require.True(t, strings.Contains(err.Error(), "native contract CryptoLib is active after height = 1"))
|
||||||
|
|
||||||
|
// Add new block => CryptoLib should be active now.
|
||||||
|
eBad.AddNewBlock(t)
|
||||||
|
ic, err = bcBad.GetTestVM(trigger.Application, nil, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
v = ic.SpawnVM()
|
||||||
|
v.LoadScriptWithHash(clState.NEF.Script, clState.Hash, callflag.All) // hash is not affected by native update history
|
||||||
|
v.Estack().PushVal(input)
|
||||||
|
v.Context().Jump(md.Offset)
|
||||||
|
|
||||||
|
require.NoError(t, v.Run())
|
||||||
|
value := v.Estack().Pop().Bytes()
|
||||||
|
require.Equal(t, hash.RipeMD160(input).BytesBE(), value)
|
||||||
})
|
})
|
||||||
eBad := neotest.NewExecutor(t, bcBad, validatorBad, committeeBad)
|
*/
|
||||||
|
|
||||||
ic, err := bcBad.GetTestVM(trigger.Application, nil, nil)
|
|
||||||
require.NoError(t, err)
|
|
||||||
v := ic.SpawnVM()
|
|
||||||
v.LoadScriptWithHash(clState.NEF.Script, clState.Hash, callflag.All) // hash is not affected by native update history
|
|
||||||
input := []byte{1, 2, 3, 4}
|
|
||||||
v.Estack().PushVal(input)
|
|
||||||
v.Context().Jump(md.Offset)
|
|
||||||
|
|
||||||
// It's prohibited to call natives before NativeUpdateHistory[0] height.
|
|
||||||
err = v.Run()
|
|
||||||
require.Error(t, err)
|
|
||||||
require.True(t, strings.Contains(err.Error(), "native contract CryptoLib is active after height = 1"))
|
|
||||||
|
|
||||||
// Add new block => CryptoLib should be active now.
|
|
||||||
eBad.AddNewBlock(t)
|
|
||||||
ic, err = bcBad.GetTestVM(trigger.Application, nil, nil)
|
|
||||||
require.NoError(t, err)
|
|
||||||
v = ic.SpawnVM()
|
|
||||||
v.LoadScriptWithHash(clState.NEF.Script, clState.Hash, callflag.All) // hash is not affected by native update history
|
|
||||||
v.Estack().PushVal(input)
|
|
||||||
v.Context().Jump(md.Offset)
|
|
||||||
|
|
||||||
require.NoError(t, v.Run())
|
|
||||||
value := v.Estack().Pop().Bytes()
|
|
||||||
require.Equal(t, hash.RipeMD160(input).BytesBE(), value)
|
|
||||||
})
|
|
||||||
|
|
||||||
manState := bc.GetContractState(e.NativeHash(t, nativenames.Management))
|
manState := bc.GetContractState(e.NativeHash(t, nativenames.Management))
|
||||||
require.NotNil(t, manState)
|
require.NotNil(t, manState)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
@ -103,6 +104,11 @@ func (l *Ledger) PostPersist(ic *interop.Context) error {
|
||||||
return nil // Actual block/tx processing is done in Blockchain.storeBlock().
|
return nil // Actual block/tx processing is done in Blockchain.storeBlock().
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (l *Ledger) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// currentHash implements currentHash SC method.
|
// currentHash implements currentHash SC method.
|
||||||
func (l *Ledger) currentHash(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
func (l *Ledger) currentHash(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||||
return stackitem.Make(ic.CurrentBlockHash().BytesBE())
|
return stackitem.Make(ic.CurrentBlockHash().BytesBE())
|
||||||
|
|
|
@ -583,12 +583,13 @@ func updateContractCache(cache *ManagementCache, cs *state.Contract) {
|
||||||
func (m *Management) OnPersist(ic *interop.Context) error {
|
func (m *Management) OnPersist(ic *interop.Context) error {
|
||||||
var cache *ManagementCache
|
var cache *ManagementCache
|
||||||
for _, native := range ic.Natives {
|
for _, native := range ic.Natives {
|
||||||
md := native.Metadata()
|
activeIn := native.ActiveIn()
|
||||||
history := md.UpdateHistory
|
if !(activeIn == nil && ic.Block.Index == 0 ||
|
||||||
if len(history) == 0 || history[0] != ic.Block.Index {
|
activeIn != nil && ic.IsHardforkActivation(*activeIn)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
md := native.Metadata()
|
||||||
cs := &state.Contract{
|
cs := &state.Contract{
|
||||||
ContractBase: md.ContractBase,
|
ContractBase: md.ContractBase,
|
||||||
}
|
}
|
||||||
|
@ -672,6 +673,11 @@ func (m *Management) Initialize(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (m *Management) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PutContractState saves given contract state into given DAO.
|
// PutContractState saves given contract state into given DAO.
|
||||||
func PutContractState(d *dao.Simple, cs *state.Contract) error {
|
func PutContractState(d *dao.Simple, cs *state.Contract) error {
|
||||||
return putContractState(d, cs, true)
|
return putContractState(d, cs, true)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
@ -136,6 +137,11 @@ func (g *GAS) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (g *GAS) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// BalanceOf returns native GAS token balance for the acc.
|
// BalanceOf returns native GAS token balance for the acc.
|
||||||
func (g *GAS) BalanceOf(d *dao.Simple, acc util.Uint160) *big.Int {
|
func (g *GAS) BalanceOf(d *dao.Simple, acc util.Uint160) *big.Int {
|
||||||
return g.balanceOfInternal(d, acc)
|
return g.balanceOfInternal(d, acc)
|
||||||
|
|
|
@ -365,6 +365,11 @@ func (n *NEO) InitializeCache(blockHeight uint32, d *dao.Simple) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (n *NEO) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (n *NEO) initConfigCache(cfg config.ProtocolConfiguration) error {
|
func (n *NEO) initConfigCache(cfg config.ProtocolConfiguration) error {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||||
|
@ -193,6 +194,11 @@ func (n *Notary) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (n *Notary) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// onPayment records the deposited amount as belonging to "from" address with a lock
|
// onPayment records the deposited amount as belonging to "from" address with a lock
|
||||||
// till the specified chain's height.
|
// till the specified chain's height.
|
||||||
func (n *Notary) onPayment(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
func (n *Notary) onPayment(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop/contract"
|
||||||
|
@ -258,6 +259,11 @@ func (o *Oracle) InitializeCache(blockHeight uint32, d *dao.Simple) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (o *Oracle) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func getResponse(tx *transaction.Transaction) *transaction.OracleResponse {
|
func getResponse(tx *transaction.Transaction) *transaction.OracleResponse {
|
||||||
for i := range tx.Attributes {
|
for i := range tx.Attributes {
|
||||||
if tx.Attributes[i].Type == transaction.OracleResponseT {
|
if tx.Attributes[i].Type == transaction.OracleResponseT {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||||
|
@ -252,6 +253,11 @@ func (p *Policy) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (p *Policy) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// getFeePerByte is a Policy contract method that returns the required transaction's fee
|
// getFeePerByte is a Policy contract method that returns the required transaction's fee
|
||||||
// per byte.
|
// per byte.
|
||||||
func (p *Policy) getFeePerByte(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
func (p *Policy) getFeePerByte(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||||
|
|
|
@ -458,6 +458,11 @@ func (s *Std) PostPersist(ic *interop.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ActiveIn implements the Contract interface.
|
||||||
|
func (s *Std) ActiveIn() *config.Hardfork {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Std) toLimitedBytes(item stackitem.Item) []byte {
|
func (s *Std) toLimitedBytes(item stackitem.Item) []byte {
|
||||||
src, err := item.TryBytes()
|
src, err := item.TryBytes()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1194,7 +1194,6 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
cs := e.chain.GetContractState((*lst)[i].Hash)
|
cs := e.chain.GetContractState((*lst)[i].Hash)
|
||||||
require.NotNil(t, cs)
|
require.NotNil(t, cs)
|
||||||
require.True(t, cs.ID <= 0)
|
require.True(t, cs.ID <= 0)
|
||||||
require.Equal(t, []uint32{0}, (*lst)[i].UpdateHistory)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue