Compare commits
12 commits
master
...
hf-dependa
Author | SHA1 | Date | |
---|---|---|---|
|
551f9ebb31 | ||
|
738ef51428 | ||
|
bc8ca6dc06 | ||
|
56a4160f21 | ||
|
9856bb7d34 | ||
|
632334180f | ||
|
c4a324db8f | ||
|
49e51a46ff | ||
|
1720222a32 | ||
|
261816d7a5 | ||
|
71d504765f | ||
|
e0825e7665 |
30 changed files with 374 additions and 155 deletions
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/testcli"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||
|
@ -237,7 +238,7 @@ func TestNEP17Transfer(t *testing.T) {
|
|||
e.CheckAwaitableTxPersisted(t)
|
||||
})
|
||||
|
||||
cmd = append(cmd, "--to", address.Uint160ToString(e.Chain.GetNotaryContractScriptHash()),
|
||||
cmd = append(cmd, "--to", address.Uint160ToString(nativehashes.Notary),
|
||||
"[", testcli.ValidatorAddr, strconv.Itoa(int(validTil)), "]")
|
||||
|
||||
t.Run("with data", func(t *testing.T) {
|
||||
|
|
|
@ -25,8 +25,9 @@ ProtocolConfiguration:
|
|||
P2PSigExtensions: true
|
||||
Hardforks:
|
||||
Aspidochelone: 3000000
|
||||
Basilisk: 4500000
|
||||
Cockatrice: 5800000
|
||||
Basilisk: 3500000
|
||||
Cockatrice: 3500000
|
||||
Domovoi: 3500000
|
||||
|
||||
ApplicationConfiguration:
|
||||
SkipBlockVerification: false
|
||||
|
|
|
@ -341,7 +341,7 @@ protocol-related settings described in the table below.
|
|||
| 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. |
|
||||
| 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>• Network payload of the `P2PNotaryRequest` type<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`). |
|
||||
| ReservedAttributes | `bool` | `false` | Allows to have reserved attributes range for experimental or private purposes. |
|
||||
| SeedList | `[]string` | [] | List of initial nodes addresses used to establish connectivity. |
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||
|
@ -81,6 +82,11 @@ func Init(t *testing.T, rootpath string, e *neotest.Executor) {
|
|||
t.Fatal("P2PSigExtensions should be enabled to init basic chain")
|
||||
}
|
||||
|
||||
const notaryDepositHeight uint32 = 8
|
||||
domovoiH, ok := e.Chain.GetConfig().Hardforks[config.HFDomovoi.String()]
|
||||
require.Truef(t, ok, "%s hardfork should be enabled since basic chain uses Notary contract", config.HFDomovoi.String())
|
||||
require.LessOrEqualf(t, domovoiH, notaryDepositHeight-1, "%s hardfork should be enabled starting from height %d, got: %d", config.HFDomovoi.String(), notaryDepositHeight-1, domovoiH)
|
||||
|
||||
var (
|
||||
// examplesPrefix is a prefix of the example smart-contracts.
|
||||
examplesPrefix = filepath.Join(rootpath, "examples")
|
||||
|
@ -189,6 +195,7 @@ func Init(t *testing.T, rootpath string, e *neotest.Executor) {
|
|||
// Block #8: deposit some GAS to notary contract for priv0.
|
||||
transferTxH = gasPriv0Invoker.Invoke(t, true, "transfer", priv0ScriptHash, notaryHash, 10_0000_0000, []any{priv0ScriptHash, int64(e.Chain.BlockHeight() + 1000)})
|
||||
t.Logf("notaryDepositTxPriv0: %v", transferTxH.StringLE())
|
||||
require.Equal(t, uint32(notaryDepositHeight), e.Chain.BlockHeight(), "notaryDepositHeight constant is out of date")
|
||||
|
||||
// Block #9: designate new Notary node.
|
||||
ntr, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, "./testdata/notary1.json"))
|
||||
|
|
|
@ -33,7 +33,6 @@ type FakeChain struct {
|
|||
txs map[util.Uint256]*transaction.Transaction
|
||||
VerifyWitnessF func() (int64, error)
|
||||
MaxVerificationGAS int64
|
||||
NotaryContractScriptHash util.Uint160
|
||||
NotaryDepositExpiration uint32
|
||||
PostBlock []func(func(*transaction.Transaction, *mempool.Pool, bool) bool, *mempool.Pool, *block.Block)
|
||||
UtilityTokenBalance *big.Int
|
||||
|
@ -111,14 +110,6 @@ func (chain *FakeChain) GetNotaryDepositExpiration(acc util.Uint160) uint32 {
|
|||
panic("TODO")
|
||||
}
|
||||
|
||||
// GetNotaryContractScriptHash implements the Blockchainer interface.
|
||||
func (chain *FakeChain) GetNotaryContractScriptHash() util.Uint160 {
|
||||
if !chain.NotaryContractScriptHash.Equals(util.Uint160{}) {
|
||||
return chain.NotaryContractScriptHash
|
||||
}
|
||||
panic("TODO")
|
||||
}
|
||||
|
||||
// GetNotaryBalance implements the Blockchainer interface.
|
||||
func (chain *FakeChain) GetNotaryBalance(acc util.Uint160) *big.Int {
|
||||
panic("TODO")
|
||||
|
|
|
@ -27,6 +27,9 @@ const (
|
|||
// https://github.com/neo-project/neo/pull/2925) and #3362 (ported from
|
||||
// https://github.com/neo-project/neo/pull/3154).
|
||||
HFCockatrice // Cockatrice
|
||||
// HFDomovoi represents hard-fork introduced in #3476 (ported from
|
||||
// https://github.com/neo-project/neo/pull/3290).
|
||||
HFDomovoi // Domovoi
|
||||
// hfLast denotes the end of hardforks enum. Consider adding new hardforks
|
||||
// before hfLast.
|
||||
hfLast
|
||||
|
|
|
@ -12,13 +12,15 @@ func _() {
|
|||
_ = x[HFAspidochelone-1]
|
||||
_ = x[HFBasilisk-2]
|
||||
_ = x[HFCockatrice-4]
|
||||
_ = x[hfLast-8]
|
||||
_ = x[HFDomovoi-8]
|
||||
_ = x[hfLast-16]
|
||||
}
|
||||
|
||||
const (
|
||||
_Hardfork_name_0 = "DefaultAspidocheloneBasilisk"
|
||||
_Hardfork_name_1 = "Cockatrice"
|
||||
_Hardfork_name_2 = "hfLast"
|
||||
_Hardfork_name_2 = "Domovoi"
|
||||
_Hardfork_name_3 = "hfLast"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -33,6 +35,8 @@ func (i Hardfork) String() string {
|
|||
return _Hardfork_name_1
|
||||
case i == 8:
|
||||
return _Hardfork_name_2
|
||||
case i == 16:
|
||||
return _Hardfork_name_3
|
||||
default:
|
||||
return "Hardfork(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mpt"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/stateroot"
|
||||
|
@ -1070,7 +1071,7 @@ func (bc *Blockchain) isHardforkEnabled(hf *config.Hardfork, blockHeight uint32)
|
|||
hfs := bc.config.Hardforks
|
||||
if hf != nil {
|
||||
start, ok := hfs[hf.String()]
|
||||
if !ok || start < blockHeight {
|
||||
if !ok || start > blockHeight {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -2104,26 +2105,30 @@ func (bc *Blockchain) GetGoverningTokenBalance(acc util.Uint160) (*big.Int, uint
|
|||
}
|
||||
|
||||
// GetNotaryBalance returns Notary deposit amount for the specified account.
|
||||
// Default value is returned if Notary contract is not yet active.
|
||||
func (bc *Blockchain) GetNotaryBalance(acc util.Uint160) *big.Int {
|
||||
if !bc.isHardforkEnabled(bc.contracts.Notary.ActiveIn(), bc.BlockHeight()) {
|
||||
return nil
|
||||
}
|
||||
return bc.contracts.Notary.BalanceOf(bc.dao, acc)
|
||||
}
|
||||
|
||||
// GetNotaryServiceFeePerKey returns a NotaryAssisted transaction attribute fee
|
||||
// per key which is a reward per notary request key for designated notary nodes.
|
||||
// Default value is returned if Notary contract is not yet active.
|
||||
func (bc *Blockchain) GetNotaryServiceFeePerKey() int64 {
|
||||
if !bc.isHardforkEnabled(&transaction.NotaryAssistedActivation, bc.BlockHeight()) {
|
||||
return 0
|
||||
}
|
||||
return bc.contracts.Policy.GetAttributeFeeInternal(bc.dao, transaction.NotaryAssistedT)
|
||||
}
|
||||
|
||||
// GetNotaryContractScriptHash returns Notary native contract hash.
|
||||
func (bc *Blockchain) GetNotaryContractScriptHash() util.Uint160 {
|
||||
if bc.P2PSigExtensionsEnabled() {
|
||||
return bc.contracts.Notary.Hash
|
||||
}
|
||||
return util.Uint160{}
|
||||
}
|
||||
|
||||
// GetNotaryDepositExpiration returns Notary deposit expiration height for the specified account.
|
||||
// Default value is returned if Notary contract is not yet active.
|
||||
func (bc *Blockchain) GetNotaryDepositExpiration(acc util.Uint160) uint32 {
|
||||
if !bc.isHardforkEnabled(bc.contracts.Notary.ActiveIn(), bc.BlockHeight()) {
|
||||
return 0
|
||||
}
|
||||
return bc.contracts.Notary.ExpirationOf(bc.dao, acc)
|
||||
}
|
||||
|
||||
|
@ -2695,10 +2700,10 @@ func (bc *Blockchain) verifyTxAttributes(d *dao.Simple, tx *transaction.Transact
|
|||
return fmt.Errorf("%w: conflicting transaction %s is already on chain", ErrInvalidAttribute, conflicts.Hash.StringLE())
|
||||
}
|
||||
case transaction.NotaryAssistedT:
|
||||
if !bc.config.P2PSigExtensions {
|
||||
return fmt.Errorf("%w: NotaryAssisted attribute was found, but P2PSigExtensions are disabled", ErrInvalidAttribute)
|
||||
if !bc.isHardforkEnabled(&transaction.NotaryAssistedActivation, bc.BlockHeight()) {
|
||||
return fmt.Errorf("%w: NotaryAssisted attribute was found, but %s is not active yet", ErrInvalidAttribute, transaction.NotaryAssistedActivation)
|
||||
}
|
||||
if !tx.HasSigner(bc.contracts.Notary.Hash) {
|
||||
if !tx.HasSigner(nativehashes.Notary) {
|
||||
return fmt.Errorf("%w: NotaryAssisted attribute was found, but transaction is not signed by the Notary native contract", ErrInvalidAttribute)
|
||||
}
|
||||
default:
|
||||
|
@ -3093,9 +3098,6 @@ func (bc *Blockchain) GetMaxVerificationGAS() int64 {
|
|||
|
||||
// GetMaxNotValidBeforeDelta returns maximum NotValidBeforeDelta Notary limit.
|
||||
func (bc *Blockchain) GetMaxNotValidBeforeDelta() (uint32, error) {
|
||||
if !bc.config.P2PSigExtensions {
|
||||
panic("disallowed call to Notary") // critical error, thus panic.
|
||||
}
|
||||
if !bc.isHardforkEnabled(bc.contracts.Notary.ActiveIn(), bc.BlockHeight()) {
|
||||
return 0, fmt.Errorf("native Notary is active starting from %s", bc.contracts.Notary.ActiveIn().String())
|
||||
}
|
||||
|
|
|
@ -370,6 +370,7 @@ func TestNewBlockchain_InitHardforks(t *testing.T) {
|
|||
config.HFAspidochelone.String(): 0,
|
||||
config.HFBasilisk.String(): 0,
|
||||
config.HFCockatrice.String(): 0,
|
||||
config.HFDomovoi.String(): 0,
|
||||
}, bc.GetConfig().Hardforks)
|
||||
})
|
||||
t.Run("empty set", func(t *testing.T) {
|
||||
|
@ -400,13 +401,14 @@ func TestNewBlockchain_InitHardforks(t *testing.T) {
|
|||
})
|
||||
t.Run("all present", func(t *testing.T) {
|
||||
bc := newTestChainWithCustomCfg(t, func(c *config.Config) {
|
||||
c.ProtocolConfiguration.Hardforks = map[string]uint32{config.HFAspidochelone.String(): 5, config.HFBasilisk.String(): 10, config.HFCockatrice.String(): 15}
|
||||
c.ProtocolConfiguration.Hardforks = map[string]uint32{config.HFAspidochelone.String(): 5, config.HFBasilisk.String(): 10, config.HFCockatrice.String(): 15, config.HFDomovoi.String(): 20}
|
||||
require.NoError(t, c.ProtocolConfiguration.Validate())
|
||||
})
|
||||
require.Equal(t, map[string]uint32{
|
||||
config.HFAspidochelone.String(): 5,
|
||||
config.HFBasilisk.String(): 10,
|
||||
config.HFCockatrice.String(): 15,
|
||||
config.HFDomovoi.String(): 20,
|
||||
}, bc.GetConfig().Hardforks)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -271,7 +271,7 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
|||
|
||||
_, _, _, err = chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, cache)
|
||||
require.Error(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("native %s: version mismatch for the latest hardfork Cockatrice (stored contract state differs from autogenerated one)", nativenames.CryptoLib)), err)
|
||||
require.True(t, strings.Contains(err.Error(), fmt.Sprintf("native %s: version mismatch for the latest hardfork Domovoi (stored contract state differs from autogenerated one)", nativenames.CryptoLib)), err)
|
||||
})
|
||||
|
||||
t.Run("good", func(t *testing.T) {
|
||||
|
@ -2057,7 +2057,12 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
|||
}
|
||||
t.Run("Disabled", func(t *testing.T) {
|
||||
bcBad, validatorBad, committeeBad := chain.NewMultiWithCustomConfig(t, func(c *config.Blockchain) {
|
||||
c.P2PSigExtensions = false
|
||||
c.P2PSigExtensions = true
|
||||
c.Hardforks = map[string]uint32{
|
||||
config.HFAspidochelone.String(): 0,
|
||||
config.HFBasilisk.String(): 0,
|
||||
config.HFCockatrice.String(): 0,
|
||||
}
|
||||
c.ReservedAttributes = false
|
||||
})
|
||||
eBad := neotest.NewExecutor(t, bcBad, validatorBad, committeeBad)
|
||||
|
@ -2069,7 +2074,7 @@ func TestBlockchain_VerifyTx(t *testing.T) {
|
|||
eBad.SignTx(t, tx, 1_0000_0000, eBad.Committee)
|
||||
err := bcBad.VerifyTx(tx)
|
||||
require.Error(t, err)
|
||||
require.True(t, strings.Contains(err.Error(), "invalid attribute: NotaryAssisted attribute was found, but P2PSigExtensions are disabled"))
|
||||
require.True(t, strings.Contains(err.Error(), "invalid attribute: NotaryAssisted attribute was found, but Domovoi is not active yet"))
|
||||
})
|
||||
t.Run("Enabled, insufficient network fee", func(t *testing.T) {
|
||||
tx := getNotaryAssistedTx(e, 1, 0)
|
||||
|
@ -2572,7 +2577,7 @@ func TestBlockchain_GenesisTransactionExtension(t *testing.T) {
|
|||
// in the right order.
|
||||
func TestNativenames(t *testing.T) {
|
||||
bc, _ := chain.NewSingleWithCustomConfig(t, func(cfg *config.Blockchain) {
|
||||
cfg.Hardforks = map[string]uint32{}
|
||||
cfg.Hardforks = nil // default (all hardforks enabled) behaviour.
|
||||
cfg.P2PSigExtensions = true
|
||||
})
|
||||
natives := bc.GetNatives()
|
||||
|
|
|
@ -247,7 +247,7 @@ func (c *ContractMD) HFSpecificContractMD(hf *config.Hardfork) *HFSpecificContra
|
|||
}
|
||||
md, ok := c.mdCache[key]
|
||||
if !ok {
|
||||
panic(fmt.Errorf("native contract descriptor cache is not initialized: contract %s, hardfork %s", c.Hash.StringLE(), key))
|
||||
panic(fmt.Errorf("native contract descriptor cache is not initialized: contract %s (%s), hardfork %s", c.Hash.StringLE(), c.Name, key))
|
||||
}
|
||||
if md == nil {
|
||||
panic(fmt.Errorf("native contract descriptor cache is nil: contract %s, hardfork %s", c.Hash.StringLE(), key))
|
||||
|
|
|
@ -72,9 +72,9 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
|||
cs.Ledger = ledger
|
||||
cs.Contracts = append(cs.Contracts, ledger)
|
||||
|
||||
gas := newGAS(int64(cfg.InitialGASSupply), cfg.P2PSigExtensions)
|
||||
gas := newGAS(int64(cfg.InitialGASSupply))
|
||||
neo := newNEO(cfg)
|
||||
policy := newPolicy(cfg.P2PSigExtensions)
|
||||
policy := newPolicy()
|
||||
neo.GAS = gas
|
||||
neo.Policy = policy
|
||||
gas.NEO = neo
|
||||
|
@ -100,7 +100,6 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
|||
cs.Oracle = oracle
|
||||
cs.Contracts = append(cs.Contracts, oracle)
|
||||
|
||||
if cfg.P2PSigExtensions {
|
||||
notary := newNotary()
|
||||
notary.GAS = gas
|
||||
notary.NEO = neo
|
||||
|
@ -108,7 +107,6 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
|
|||
notary.Policy = policy
|
||||
cs.Notary = notary
|
||||
cs.Contracts = append(cs.Contracts, notary)
|
||||
}
|
||||
|
||||
return cs
|
||||
}
|
||||
|
|
|
@ -610,8 +610,6 @@ func (m *Management) OnPersist(ic *interop.Context) error {
|
|||
for _, hf := range config.Hardforks {
|
||||
if _, ok := activeHFs[hf]; ok && ic.IsHardforkActivation(hf) {
|
||||
isUpdate = true
|
||||
activation := hf // avoid loop variable pointer exporting.
|
||||
activeIn = &activation // reuse ActiveIn variable for the initialization hardfork.
|
||||
// Break immediately since native Initialize should be called starting from the first hardfork in a raw
|
||||
// (if there are multiple hardforks with the same enabling height).
|
||||
break
|
||||
|
@ -626,6 +624,10 @@ func (m *Management) OnPersist(ic *interop.Context) error {
|
|||
currentActiveHFs = append(currentActiveHFs, hf)
|
||||
}
|
||||
}
|
||||
// activeIn is not included into the activeHFs list.
|
||||
if activeIn != nil && activeIn.Cmp(latestHF) > 0 {
|
||||
latestHF = *activeIn
|
||||
}
|
||||
if !(isDeploy || isUpdate) {
|
||||
continue
|
||||
}
|
||||
|
@ -668,7 +670,7 @@ func (m *Management) OnPersist(ic *interop.Context) error {
|
|||
// The rest of activating hardforks also require initialization.
|
||||
for _, hf := range currentActiveHFs {
|
||||
if err := native.Initialize(ic, &hf, hfSpecificMD); err != nil {
|
||||
return fmt.Errorf("initializing %s native contract at HF %d: %w", md.Name, activeIn, err)
|
||||
return fmt.Errorf("initializing %s native contract at HF %d: %w", md.Name, hf, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
|
||||
func TestDeployGetUpdateDestroyContract(t *testing.T) {
|
||||
mgmt := newManagement()
|
||||
mgmt.Policy = newPolicy(false)
|
||||
mgmt.Policy = newPolicy()
|
||||
d := dao.NewSimple(storage.NewMemoryStore(), false)
|
||||
ic := &interop.Context{DAO: d}
|
||||
err := mgmt.Initialize(ic, nil, nil)
|
||||
|
@ -95,7 +95,7 @@ func TestManagement_Initialize(t *testing.T) {
|
|||
|
||||
func TestManagement_GetNEP17Contracts(t *testing.T) {
|
||||
mgmt := newManagement()
|
||||
mgmt.Policy = newPolicy(false)
|
||||
mgmt.Policy = newPolicy()
|
||||
d := dao.NewSimple(storage.NewMemoryStore(), false)
|
||||
err := mgmt.Initialize(&interop.Context{DAO: d}, nil, nil)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -23,7 +23,6 @@ type GAS struct {
|
|||
Policy *Policy
|
||||
|
||||
initialSupply int64
|
||||
p2pSigExtensionsEnabled bool
|
||||
}
|
||||
|
||||
const gasContractID = -6
|
||||
|
@ -32,10 +31,9 @@ const gasContractID = -6
|
|||
const GASFactor = NEOTotalSupply
|
||||
|
||||
// newGAS returns GAS native contract.
|
||||
func newGAS(init int64, p2pSigExtensionsEnabled bool) *GAS {
|
||||
func newGAS(init int64) *GAS {
|
||||
g := &GAS{
|
||||
initialSupply: init,
|
||||
p2pSigExtensionsEnabled: p2pSigExtensionsEnabled,
|
||||
}
|
||||
defer g.BuildHFSpecificMD(g.ActiveIn())
|
||||
|
||||
|
@ -122,7 +120,6 @@ func (g *GAS) OnPersist(ic *interop.Context) error {
|
|||
var netFee int64
|
||||
for _, tx := range ic.Block.Transactions {
|
||||
netFee += tx.NetworkFee
|
||||
if g.p2pSigExtensionsEnabled {
|
||||
// Reward for NotaryAssisted attribute will be minted to designated notary nodes
|
||||
// by Notary contract.
|
||||
attrs := tx.GetAttributes(transaction.NotaryAssistedT)
|
||||
|
@ -131,7 +128,6 @@ func (g *GAS) OnPersist(ic *interop.Context) error {
|
|||
netFee -= (int64(na.NKeys) + 1) * g.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
|
||||
}
|
||||
}
|
||||
}
|
||||
g.mint(ic, primary, big.NewInt(int64(netFee)), false)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ var (
|
|||
nativenames.Policy: `{"id":-7,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"PolicyContract","abi":{"methods":[{"name":"blockAccount","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":false},{"name":"getAttributeFee","offset":7,"parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","safe":true},{"name":"getExecFeeFactor","offset":14,"parameters":[],"returntype":"Integer","safe":true},{"name":"getFeePerByte","offset":21,"parameters":[],"returntype":"Integer","safe":true},{"name":"getStoragePrice","offset":28,"parameters":[],"returntype":"Integer","safe":true},{"name":"isBlocked","offset":35,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":true},{"name":"setAttributeFee","offset":42,"parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setExecFeeFactor","offset":49,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setFeePerByte","offset":56,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setStoragePrice","offset":63,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"unblockAccount","offset":70,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":false}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
nativenames.Designation: `{"id":-8,"hash":"0x49cf4e5378ffcd4dec034fd98a174c5491e395e2","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0A=","checksum":983638438},"manifest":{"name":"RoleManagement","abi":{"methods":[{"name":"designateAsRole","offset":0,"parameters":[{"name":"role","type":"Integer"},{"name":"nodes","type":"Array"}],"returntype":"Void","safe":false},{"name":"getDesignatedByRole","offset":7,"parameters":[{"name":"role","type":"Integer"},{"name":"index","type":"Integer"}],"returntype":"Array","safe":true}],"events":[{"name":"Designation","parameters":[{"name":"Role","type":"Integer"},{"name":"BlockIndex","type":"Integer"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
nativenames.Oracle: `{"id":-9,"hash":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":2663858513},"manifest":{"name":"OracleContract","abi":{"methods":[{"name":"finish","offset":0,"parameters":[],"returntype":"Void","safe":false},{"name":"getPrice","offset":7,"parameters":[],"returntype":"Integer","safe":true},{"name":"request","offset":14,"parameters":[{"name":"url","type":"String"},{"name":"filter","type":"String"},{"name":"callback","type":"String"},{"name":"userData","type":"Any"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setPrice","offset":21,"parameters":[{"name":"price","type":"Integer"}],"returntype":"Void","safe":false},{"name":"verify","offset":28,"parameters":[],"returntype":"Boolean","safe":true}],"events":[{"name":"OracleRequest","parameters":[{"name":"Id","type":"Integer"},{"name":"RequestContract","type":"Hash160"},{"name":"Url","type":"String"},{"name":"Filter","type":"String"}]},{"name":"OracleResponse","parameters":[{"name":"Id","type":"Integer"},{"name":"OriginalTx","type":"Hash256"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
nativenames.Notary: `{"id":-10,"hash":"0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"Notary","abi":{"methods":[{"name":"balanceOf","offset":0,"parameters":[{"name":"addr","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"expirationOf","offset":7,"parameters":[{"name":"addr","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"getMaxNotValidBeforeDelta","offset":14,"parameters":[],"returntype":"Integer","safe":true},{"name":"lockDepositUntil","offset":21,"parameters":[{"name":"address","type":"Hash160"},{"name":"till","type":"Integer"}],"returntype":"Boolean","safe":false},{"name":"onNEP17Payment","offset":28,"parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false},{"name":"setMaxNotValidBeforeDelta","offset":35,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"verify","offset":42,"parameters":[{"name":"signature","type":"Signature"}],"returntype":"Boolean","safe":true},{"name":"withdraw","offset":49,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"}],"returntype":"Boolean","safe":false}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
}
|
||||
// cockatriceCSS holds serialized native contract states built for genesis block (with UpdateCounter 0)
|
||||
// under assumption that hardforks from Aspidochelone to Cockatrice (included) are enabled.
|
||||
|
@ -55,6 +54,12 @@ var (
|
|||
nativenames.CryptoLib: `{"id":-3,"hash":"0x726cb6e0cd8628a1350a611384688911ab75f51b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"CryptoLib","abi":{"methods":[{"name":"bls12381Add","offset":0,"parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"InteropInterface","safe":true},{"name":"bls12381Deserialize","offset":7,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"InteropInterface","safe":true},{"name":"bls12381Equal","offset":14,"parameters":[{"name":"x","type":"InteropInterface"},{"name":"y","type":"InteropInterface"}],"returntype":"Boolean","safe":true},{"name":"bls12381Mul","offset":21,"parameters":[{"name":"x","type":"InteropInterface"},{"name":"mul","type":"ByteArray"},{"name":"neg","type":"Boolean"}],"returntype":"InteropInterface","safe":true},{"name":"bls12381Pairing","offset":28,"parameters":[{"name":"g1","type":"InteropInterface"},{"name":"g2","type":"InteropInterface"}],"returntype":"InteropInterface","safe":true},{"name":"bls12381Serialize","offset":35,"parameters":[{"name":"g","type":"InteropInterface"}],"returntype":"ByteArray","safe":true},{"name":"keccak256","offset":42,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"murmur32","offset":49,"parameters":[{"name":"data","type":"ByteArray"},{"name":"seed","type":"Integer"}],"returntype":"ByteArray","safe":true},{"name":"ripemd160","offset":56,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"sha256","offset":63,"parameters":[{"name":"data","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"verifyWithECDsa","offset":70,"parameters":[{"name":"message","type":"ByteArray"},{"name":"pubkey","type":"ByteArray"},{"name":"signature","type":"ByteArray"},{"name":"curveHash","type":"Integer"}],"returntype":"Boolean","safe":true}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
nativenames.Neo: `{"id":-5,"hash":"0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1325686241},"manifest":{"name":"NeoToken","abi":{"methods":[{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"decimals","offset":7,"parameters":[],"returntype":"Integer","safe":true},{"name":"getAccountState","offset":14,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Array","safe":true},{"name":"getAllCandidates","offset":21,"parameters":[],"returntype":"InteropInterface","safe":true},{"name":"getCandidateVote","offset":28,"parameters":[{"name":"pubKey","type":"PublicKey"}],"returntype":"Integer","safe":true},{"name":"getCandidates","offset":35,"parameters":[],"returntype":"Array","safe":true},{"name":"getCommittee","offset":42,"parameters":[],"returntype":"Array","safe":true},{"name":"getCommitteeAddress","offset":49,"parameters":[],"returntype":"Hash160","safe":true},{"name":"getGasPerBlock","offset":56,"parameters":[],"returntype":"Integer","safe":true},{"name":"getNextBlockValidators","offset":63,"parameters":[],"returntype":"Array","safe":true},{"name":"getRegisterPrice","offset":70,"parameters":[],"returntype":"Integer","safe":true},{"name":"registerCandidate","offset":77,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","safe":false},{"name":"setGasPerBlock","offset":84,"parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setRegisterPrice","offset":91,"parameters":[{"name":"registerPrice","type":"Integer"}],"returntype":"Void","safe":false},{"name":"symbol","offset":98,"parameters":[],"returntype":"String","safe":true},{"name":"totalSupply","offset":105,"parameters":[],"returntype":"Integer","safe":true},{"name":"transfer","offset":112,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Boolean","safe":false},{"name":"unclaimedGas","offset":119,"parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer","safe":true},{"name":"unregisterCandidate","offset":126,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean","safe":false},{"name":"vote","offset":133,"parameters":[{"name":"account","type":"Hash160"},{"name":"voteTo","type":"PublicKey"}],"returntype":"Boolean","safe":false}],"events":[{"name":"Transfer","parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}]},{"name":"CandidateStateChanged","parameters":[{"name":"pubkey","type":"PublicKey"},{"name":"registered","type":"Boolean"},{"name":"votes","type":"Integer"}]},{"name":"Vote","parameters":[{"name":"account","type":"Hash160"},{"name":"from","type":"PublicKey"},{"name":"to","type":"PublicKey"},{"name":"amount","type":"Integer"}]},{"name":"CommitteeChanged","parameters":[{"name":"old","type":"Array"},{"name":"new","type":"Array"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-17"],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
}
|
||||
// domovoiCSS holds serialized native contract states built for genesis block (with UpdateCounter 0)
|
||||
// under assumption that hardforks from Aspidochelone to Domovoi (included) are enabled.
|
||||
domovoiCSS = map[string]string{
|
||||
nativenames.Notary: `{"id":-10,"hash":"0xc1e14f19c3e60d0b9244d06dd7ba9b113135ec3b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1110259869},"manifest":{"name":"Notary","abi":{"methods":[{"name":"balanceOf","offset":0,"parameters":[{"name":"addr","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"expirationOf","offset":7,"parameters":[{"name":"addr","type":"Hash160"}],"returntype":"Integer","safe":true},{"name":"getMaxNotValidBeforeDelta","offset":14,"parameters":[],"returntype":"Integer","safe":true},{"name":"lockDepositUntil","offset":21,"parameters":[{"name":"address","type":"Hash160"},{"name":"till","type":"Integer"}],"returntype":"Boolean","safe":false},{"name":"onNEP17Payment","offset":28,"parameters":[{"name":"from","type":"Hash160"},{"name":"amount","type":"Integer"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false},{"name":"setMaxNotValidBeforeDelta","offset":35,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"verify","offset":42,"parameters":[{"name":"signature","type":"Signature"}],"returntype":"Boolean","safe":true},{"name":"withdraw","offset":49,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"}],"returntype":"Boolean","safe":false}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
nativenames.Policy: `{"id":-7,"hash":"0xcc5e4edd9f5f8dba8bb65734541df7a1c081c67b","nef":{"magic":860243278,"compiler":"neo-core-v3.0","source":"","tokens":[],"script":"EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=","checksum":1094259016},"manifest":{"name":"PolicyContract","abi":{"methods":[{"name":"blockAccount","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":false},{"name":"getAttributeFee","offset":7,"parameters":[{"name":"attributeType","type":"Integer"}],"returntype":"Integer","safe":true},{"name":"getExecFeeFactor","offset":14,"parameters":[],"returntype":"Integer","safe":true},{"name":"getFeePerByte","offset":21,"parameters":[],"returntype":"Integer","safe":true},{"name":"getStoragePrice","offset":28,"parameters":[],"returntype":"Integer","safe":true},{"name":"isBlocked","offset":35,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":true},{"name":"setAttributeFee","offset":42,"parameters":[{"name":"attributeType","type":"Integer"},{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setExecFeeFactor","offset":49,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setFeePerByte","offset":56,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"setStoragePrice","offset":63,"parameters":[{"name":"value","type":"Integer"}],"returntype":"Void","safe":false},{"name":"unblockAccount","offset":70,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Boolean","safe":false}],"events":[]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"extra":null},"updatecounter":0}`,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -63,6 +68,11 @@ func init() {
|
|||
cockatriceCSS[k] = v
|
||||
}
|
||||
}
|
||||
for k, v := range cockatriceCSS {
|
||||
if _, ok := domovoiCSS[k]; !ok {
|
||||
domovoiCSS[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newManagementClient(t *testing.T) *neotest.ContractInvoker {
|
||||
|
@ -91,6 +101,10 @@ func TestManagement_GenesisNativeState(t *testing.T) {
|
|||
h := state.CreateNativeContractHash(name)
|
||||
c.InvokeAndCheck(t, func(t testing.TB, stack []stackitem.Item) {
|
||||
si := stack[0]
|
||||
if _, ok := expected[name]; !ok {
|
||||
require.Equal(t, stackitem.Null{}, si, fmt.Errorf("contract %s state found", name))
|
||||
return
|
||||
}
|
||||
var cs = &state.Contract{}
|
||||
require.NoError(t, cs.FromStackItem(si), name)
|
||||
jBytes, err := ojson.Marshal(cs)
|
||||
|
@ -113,6 +127,7 @@ func TestManagement_GenesisNativeState(t *testing.T) {
|
|||
config.HFAspidochelone.String(): 100500,
|
||||
config.HFBasilisk.String(): 100500,
|
||||
config.HFCockatrice.String(): 100500,
|
||||
config.HFDomovoi.String(): 100500,
|
||||
}
|
||||
cfg.P2PSigExtensions = true
|
||||
})
|
||||
|
@ -148,15 +163,31 @@ func TestManagement_GenesisNativeState(t *testing.T) {
|
|||
})
|
||||
check(t, mgmt, cockatriceCSS)
|
||||
})
|
||||
t.Run("Domovoi enabled", func(t *testing.T) {
|
||||
mgmt := newCustomManagementClient(t, func(cfg *config.Blockchain) {
|
||||
cfg.Hardforks = map[string]uint32{
|
||||
config.HFAspidochelone.String(): 0,
|
||||
config.HFBasilisk.String(): 0,
|
||||
config.HFCockatrice.String(): 0,
|
||||
config.HFDomovoi.String(): 0,
|
||||
}
|
||||
cfg.P2PSigExtensions = true
|
||||
})
|
||||
check(t, mgmt, domovoiCSS)
|
||||
})
|
||||
}
|
||||
|
||||
func TestManagement_NativeDeployUpdateNotifications(t *testing.T) {
|
||||
const cockatriceHeight = 3
|
||||
const (
|
||||
cockatriceHeight = 3
|
||||
domovoiHeight = 5
|
||||
)
|
||||
mgmt := newCustomManagementClient(t, func(cfg *config.Blockchain) {
|
||||
cfg.Hardforks = map[string]uint32{
|
||||
config.HFAspidochelone.String(): 0,
|
||||
config.HFBasilisk.String(): 0,
|
||||
config.HFCockatrice.String(): cockatriceHeight,
|
||||
config.HFDomovoi.String(): domovoiHeight,
|
||||
}
|
||||
cfg.P2PSigExtensions = true
|
||||
})
|
||||
|
@ -169,6 +200,8 @@ func TestManagement_NativeDeployUpdateNotifications(t *testing.T) {
|
|||
var expected []state.NotificationEvent
|
||||
for _, name := range nativenames.All {
|
||||
switch name {
|
||||
case nativenames.Notary:
|
||||
continue
|
||||
case nativenames.Gas:
|
||||
expected = append(expected, state.NotificationEvent{
|
||||
ScriptHash: nativehashes.GasToken,
|
||||
|
@ -200,7 +233,7 @@ func TestManagement_NativeDeployUpdateNotifications(t *testing.T) {
|
|||
}
|
||||
require.Equal(t, expected, aer[0].Events)
|
||||
|
||||
// Generate some blocks and check Update notifications.
|
||||
// Generate some blocks and check Update notifications for Cockatrice hardfork.
|
||||
cockatriceBlock := mgmt.GenerateNewBlocks(t, cockatriceHeight)[cockatriceHeight-1]
|
||||
aer, err = mgmt.Chain.GetAppExecResults(cockatriceBlock.Hash(), trigger.OnPersist)
|
||||
require.NoError(t, err)
|
||||
|
@ -216,15 +249,42 @@ func TestManagement_NativeDeployUpdateNotifications(t *testing.T) {
|
|||
})
|
||||
}
|
||||
require.Equal(t, expected, aer[0].Events)
|
||||
|
||||
// Generate some blocks and check Deploy notifications for Domovoi hardfork.
|
||||
mgmt.GenerateNewBlocks(t, domovoiHeight-int(mgmt.Chain.BlockHeight()))
|
||||
aer, err = mgmt.Chain.GetAppExecResults(mgmt.Chain.GetHeaderHash(mgmt.Chain.BlockHeight()), trigger.OnPersist)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(aer))
|
||||
expected = expected[:0]
|
||||
expected = append(expected, state.NotificationEvent{
|
||||
ScriptHash: nativehashes.ContractManagement,
|
||||
Name: "Update",
|
||||
Item: stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.Make(nativehashes.PolicyContract),
|
||||
}),
|
||||
})
|
||||
expected = append(expected, state.NotificationEvent{
|
||||
ScriptHash: nativehashes.ContractManagement,
|
||||
Name: "Deploy",
|
||||
Item: stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.Make(nativehashes.Notary),
|
||||
}),
|
||||
})
|
||||
require.Equal(t, expected, aer[0].Events)
|
||||
}
|
||||
|
||||
func TestManagement_NativeUpdate(t *testing.T) {
|
||||
const cockatriceHeight = 3
|
||||
const (
|
||||
cockatriceHeight = 3
|
||||
domovoiHeight = 6
|
||||
)
|
||||
|
||||
c := newCustomManagementClient(t, func(cfg *config.Blockchain) {
|
||||
cfg.Hardforks = map[string]uint32{
|
||||
config.HFAspidochelone.String(): 0,
|
||||
config.HFBasilisk.String(): 0,
|
||||
config.HFCockatrice.String(): cockatriceHeight,
|
||||
config.HFDomovoi.String(): domovoiHeight,
|
||||
}
|
||||
cfg.P2PSigExtensions = true
|
||||
})
|
||||
|
@ -235,7 +295,12 @@ func TestManagement_NativeUpdate(t *testing.T) {
|
|||
for _, name := range nativenames.All {
|
||||
h := state.CreateNativeContractHash(name)
|
||||
cs := c.Chain.GetContractState(h)
|
||||
if name == nativenames.Notary {
|
||||
require.Nil(t, cs, name)
|
||||
continue
|
||||
} else {
|
||||
require.NotNil(t, cs, name)
|
||||
}
|
||||
jBytes, err := ojson.Marshal(cs)
|
||||
require.NoError(t, err, name)
|
||||
require.Equal(t, defaultCSS[name], string(jBytes), fmt.Errorf("contract %s state mismatch", name))
|
||||
|
@ -247,16 +312,50 @@ func TestManagement_NativeUpdate(t *testing.T) {
|
|||
for _, name := range nativenames.All {
|
||||
h := state.CreateNativeContractHash(name)
|
||||
cs := c.Chain.GetContractState(h)
|
||||
if name == nativenames.Notary {
|
||||
require.Nil(t, cs, name)
|
||||
continue
|
||||
} else {
|
||||
require.NotNil(t, cs, name)
|
||||
}
|
||||
var actual = cs
|
||||
if name == nativenames.Neo || name == nativenames.CryptoLib {
|
||||
// A tiny hack to reuse cockatriceCSS map in the check below.
|
||||
require.Equal(t, uint16(1), cs.UpdateCounter, name)
|
||||
cs.UpdateCounter--
|
||||
cp := *cs
|
||||
actual = &cp // avoid Management cache corruption.
|
||||
actual.UpdateCounter--
|
||||
}
|
||||
jBytes, err := ojson.Marshal(cs)
|
||||
jBytes, err := ojson.Marshal(actual)
|
||||
require.NoError(t, err, name)
|
||||
require.Equal(t, cockatriceCSS[name], string(jBytes), fmt.Errorf("contract %s state mismatch", name))
|
||||
}
|
||||
|
||||
// Add some blocks up to the Domovoi enabling height and check the natives state.
|
||||
for i := c.Chain.BlockHeight(); i < domovoiHeight-1; i++ {
|
||||
c.AddNewBlock(t)
|
||||
for _, name := range nativenames.All {
|
||||
h := state.CreateNativeContractHash(name)
|
||||
cs := c.Chain.GetContractState(h)
|
||||
if name == nativenames.Notary {
|
||||
require.Nil(t, cs, name)
|
||||
continue
|
||||
} else {
|
||||
require.NotNil(t, cs, name)
|
||||
}
|
||||
var actual = cs
|
||||
if name == nativenames.Neo || name == nativenames.CryptoLib {
|
||||
// A tiny hack to reuse domovoiCSS map in the check below.
|
||||
require.Equal(t, uint16(1), cs.UpdateCounter, name)
|
||||
cp := *cs
|
||||
actual = &cp // avoid Management cache corruption.
|
||||
actual.UpdateCounter--
|
||||
}
|
||||
jBytes, err := ojson.Marshal(actual)
|
||||
require.NoError(t, err, name)
|
||||
require.Equal(t, domovoiCSS[name], string(jBytes), fmt.Errorf("contract %s state mismatch", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagement_NativeUpdate_Call(t *testing.T) {
|
||||
|
@ -292,12 +391,16 @@ func TestManagement_NativeUpdate_Call(t *testing.T) {
|
|||
// different block heights depending on hardfork settings. This test is located here since it
|
||||
// depends on defaultCSS and cockatriceCSS.
|
||||
func TestBlockchain_GetNatives(t *testing.T) {
|
||||
const cockatriceHeight = 3
|
||||
const (
|
||||
cockatriceHeight = 3
|
||||
domovoiHeight = 6
|
||||
)
|
||||
bc, acc := chain.NewSingleWithCustomConfig(t, func(cfg *config.Blockchain) {
|
||||
cfg.Hardforks = map[string]uint32{
|
||||
config.HFAspidochelone.String(): 0,
|
||||
config.HFBasilisk.String(): 0,
|
||||
config.HFCockatrice.String(): cockatriceHeight,
|
||||
config.HFDomovoi.String(): domovoiHeight,
|
||||
}
|
||||
cfg.P2PSigExtensions = true
|
||||
})
|
||||
|
@ -305,7 +408,7 @@ func TestBlockchain_GetNatives(t *testing.T) {
|
|||
|
||||
// Check genesis-based native contract states.
|
||||
natives := bc.GetNatives()
|
||||
require.Equal(t, len(nativenames.All), len(natives))
|
||||
require.Equal(t, len(nativenames.All)-1, len(natives)) // Notary is deployed starting from D hardfork.
|
||||
for _, cs := range natives {
|
||||
csFull := state.Contract{
|
||||
ContractBase: cs.ContractBase,
|
||||
|
@ -316,10 +419,10 @@ func TestBlockchain_GetNatives(t *testing.T) {
|
|||
require.Equal(t, defaultCSS[cs.Manifest.Name], string(jBytes), fmt.Errorf("contract %s state mismatch", cs.Manifest.Name))
|
||||
}
|
||||
|
||||
// Check native state after update.
|
||||
// Check native state after Cockatrice.
|
||||
e.GenerateNewBlocks(t, cockatriceHeight)
|
||||
natives = bc.GetNatives()
|
||||
require.Equal(t, len(nativenames.All), len(natives))
|
||||
require.Equal(t, len(nativenames.All)-1, len(natives)) // Notary is deployed starting from D hardfork.
|
||||
for _, cs := range natives {
|
||||
csFull := state.Contract{
|
||||
ContractBase: cs.ContractBase,
|
||||
|
@ -329,6 +432,20 @@ func TestBlockchain_GetNatives(t *testing.T) {
|
|||
require.NoError(t, err, cs.Manifest.Name)
|
||||
require.Equal(t, cockatriceCSS[cs.Manifest.Name], string(jBytes), fmt.Errorf("contract %s state mismatch", cs.Manifest.Name))
|
||||
}
|
||||
|
||||
// Check native state after Domovoi.
|
||||
e.GenerateNewBlocks(t, domovoiHeight-cockatriceHeight)
|
||||
natives = bc.GetNatives()
|
||||
require.Equal(t, len(nativenames.All), len(natives))
|
||||
for _, cs := range natives {
|
||||
csFull := state.Contract{
|
||||
ContractBase: cs.ContractBase,
|
||||
UpdateCounter: 0, // Since we're comparing only state.NativeContract part, set the update counter to 0 to match the domovoiCSS.
|
||||
}
|
||||
jBytes, err := ojson.Marshal(csFull)
|
||||
require.NoError(t, err, cs.Manifest.Name)
|
||||
require.Equal(t, domovoiCSS[cs.Manifest.Name], string(jBytes), fmt.Errorf("contract %s state mismatch", cs.Manifest.Name))
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagement_ContractCache(t *testing.T) {
|
||||
|
|
|
@ -52,7 +52,10 @@ const (
|
|||
defaultMaxNotValidBeforeDelta = 140 // 20 rounds for 7 validators, a little more than half an hour
|
||||
)
|
||||
|
||||
var maxNotValidBeforeDeltaKey = []byte{10}
|
||||
var (
|
||||
maxNotValidBeforeDeltaKey = []byte{10}
|
||||
activeIn = config.HFDomovoi
|
||||
)
|
||||
|
||||
var (
|
||||
_ interop.Contract = (*Notary)(nil)
|
||||
|
@ -200,7 +203,7 @@ func (n *Notary) PostPersist(ic *interop.Context) error {
|
|||
|
||||
// ActiveIn implements the Contract interface.
|
||||
func (n *Notary) ActiveIn() *config.Hardfork {
|
||||
return nil
|
||||
return &activeIn
|
||||
}
|
||||
|
||||
// onPayment records the deposited amount as belonging to "from" address with a lock
|
||||
|
|
|
@ -63,9 +63,6 @@ var (
|
|||
type Policy struct {
|
||||
interop.ContractMD
|
||||
NEO *NEO
|
||||
|
||||
// p2pSigExtensionsEnabled defines whether the P2P signature extensions logic is relevant.
|
||||
p2pSigExtensionsEnabled bool
|
||||
}
|
||||
|
||||
type PolicyCache struct {
|
||||
|
@ -100,11 +97,8 @@ func copyPolicyCache(src, dst *PolicyCache) {
|
|||
}
|
||||
|
||||
// newPolicy returns Policy native contract.
|
||||
func newPolicy(p2pSigExtensionsEnabled bool) *Policy {
|
||||
p := &Policy{
|
||||
ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID),
|
||||
p2pSigExtensionsEnabled: p2pSigExtensionsEnabled,
|
||||
}
|
||||
func newPolicy() *Policy {
|
||||
p := &Policy{ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID)}
|
||||
defer p.BuildHFSpecificMD(p.ActiveIn())
|
||||
|
||||
desc := newDescriptor("getFeePerByte", smartcontract.IntegerType)
|
||||
|
@ -136,13 +130,24 @@ func newPolicy(p2pSigExtensionsEnabled bool) *Policy {
|
|||
|
||||
desc = newDescriptor("getAttributeFee", smartcontract.IntegerType,
|
||||
manifest.NewParameter("attributeType", smartcontract.IntegerType))
|
||||
md = newMethodAndPrice(p.getAttributeFee, 1<<15, callflag.ReadStates)
|
||||
md = newMethodAndPrice(p.getAttributeFeeV0, 1<<15, callflag.ReadStates, config.HFDefault, transaction.NotaryAssistedActivation)
|
||||
p.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("getAttributeFee", smartcontract.IntegerType,
|
||||
manifest.NewParameter("attributeType", smartcontract.IntegerType))
|
||||
md = newMethodAndPrice(p.getAttributeFeeV1, 1<<15, callflag.ReadStates, transaction.NotaryAssistedActivation)
|
||||
p.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("setAttributeFee", smartcontract.VoidType,
|
||||
manifest.NewParameter("attributeType", smartcontract.IntegerType),
|
||||
manifest.NewParameter("value", smartcontract.IntegerType))
|
||||
md = newMethodAndPrice(p.setAttributeFee, 1<<15, callflag.States)
|
||||
md = newMethodAndPrice(p.setAttributeFeeV0, 1<<15, callflag.States, config.HFDefault, transaction.NotaryAssistedActivation)
|
||||
p.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("setAttributeFee", smartcontract.VoidType,
|
||||
manifest.NewParameter("attributeType", smartcontract.IntegerType),
|
||||
manifest.NewParameter("value", smartcontract.IntegerType))
|
||||
md = newMethodAndPrice(p.setAttributeFeeV1, 1<<15, callflag.States, transaction.NotaryAssistedActivation)
|
||||
p.AddMethod(md, desc)
|
||||
|
||||
desc = newDescriptor("setFeePerByte", smartcontract.VoidType,
|
||||
|
@ -170,10 +175,7 @@ func (p *Policy) Metadata() *interop.ContractMD {
|
|||
|
||||
// Initialize initializes Policy native contract and implements the Contract interface.
|
||||
func (p *Policy) Initialize(ic *interop.Context, hf *config.Hardfork, newMD *interop.HFSpecificContractMD) error {
|
||||
if hf != p.ActiveIn() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if hf == p.ActiveIn() {
|
||||
setIntWithKey(p.ID, ic.DAO, feePerByteKey, defaultFeePerByte)
|
||||
setIntWithKey(p.ID, ic.DAO, execFeeFactorKey, defaultExecFeeFactor)
|
||||
setIntWithKey(p.ID, ic.DAO, storagePriceKey, DefaultStoragePrice)
|
||||
|
@ -186,11 +188,14 @@ func (p *Policy) Initialize(ic *interop.Context, hf *config.Hardfork, newMD *int
|
|||
attributeFee: map[transaction.AttrType]uint32{},
|
||||
blockedAccounts: make([]util.Uint160, 0),
|
||||
}
|
||||
if p.p2pSigExtensionsEnabled {
|
||||
ic.DAO.SetCache(p.ID, cache)
|
||||
}
|
||||
if hf != nil && *hf == transaction.NotaryAssistedActivation {
|
||||
setIntWithKey(p.ID, ic.DAO, []byte{attributeFeePrefix, byte(transaction.NotaryAssistedT)}, defaultNotaryAssistedFee)
|
||||
|
||||
cache := ic.DAO.GetRWCache(p.ID).(*PolicyCache)
|
||||
cache.attributeFee[transaction.NotaryAssistedT] = defaultNotaryAssistedFee
|
||||
}
|
||||
ic.DAO.SetCache(p.ID, cache)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -363,9 +368,18 @@ func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) sta
|
|||
return stackitem.Null{}
|
||||
}
|
||||
|
||||
func (p *Policy) getAttributeFee(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
func (p *Policy) getAttributeFeeV0(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
return p.getAttributeFeeGeneric(ic, args, false)
|
||||
}
|
||||
|
||||
func (p *Policy) getAttributeFeeV1(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
return p.getAttributeFeeGeneric(ic, args, true)
|
||||
}
|
||||
|
||||
func (p *Policy) getAttributeFeeGeneric(ic *interop.Context, args []stackitem.Item, allowNotaryAssisted bool) stackitem.Item {
|
||||
t := transaction.AttrType(toUint8(args[0]))
|
||||
if !transaction.IsValidAttrType(ic.Chain.GetConfig().ReservedAttributes, t) {
|
||||
if !transaction.IsValidAttrType(ic.Chain.GetConfig().ReservedAttributes, t) ||
|
||||
(!allowNotaryAssisted && t == transaction.NotaryAssistedT) {
|
||||
panic(fmt.Errorf("invalid attribute type: %d", t))
|
||||
}
|
||||
return stackitem.NewBigInteger(big.NewInt(p.GetAttributeFeeInternal(ic.DAO, t)))
|
||||
|
@ -382,10 +396,19 @@ func (p *Policy) GetAttributeFeeInternal(d *dao.Simple, t transaction.AttrType)
|
|||
return int64(v)
|
||||
}
|
||||
|
||||
func (p *Policy) setAttributeFee(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
func (p *Policy) setAttributeFeeV0(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
return p.setAttributeFeeGeneric(ic, args, false)
|
||||
}
|
||||
|
||||
func (p *Policy) setAttributeFeeV1(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
return p.setAttributeFeeGeneric(ic, args, true)
|
||||
}
|
||||
|
||||
func (p *Policy) setAttributeFeeGeneric(ic *interop.Context, args []stackitem.Item, allowNotaryAssisted bool) stackitem.Item {
|
||||
t := transaction.AttrType(toUint8(args[0]))
|
||||
value := toUint32(args[1])
|
||||
if !transaction.IsValidAttrType(ic.Chain.GetConfig().ReservedAttributes, t) {
|
||||
if !transaction.IsValidAttrType(ic.Chain.GetConfig().ReservedAttributes, t) ||
|
||||
(!allowNotaryAssisted && t == transaction.NotaryAssistedT) {
|
||||
panic(fmt.Errorf("invalid attribute type: %d", t))
|
||||
}
|
||||
if value > maxAttributeFee {
|
||||
|
|
|
@ -4,9 +4,12 @@ import (
|
|||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/neotest/chain"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
@ -65,3 +68,51 @@ func TestPolicy_BlockedAccounts(t *testing.T) {
|
|||
require.Equal(t, expectedErr, err.Error())
|
||||
})
|
||||
}
|
||||
|
||||
func TestPolicy_GetNotaryFeePerKey(t *testing.T) {
|
||||
const domovoiHeight = 4
|
||||
bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
|
||||
c.Hardforks = map[string]uint32{
|
||||
config.HFDomovoi.String(): domovoiHeight,
|
||||
}
|
||||
})
|
||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||
p := e.CommitteeInvoker(nativehashes.PolicyContract)
|
||||
|
||||
// Invoke before Domovoi should fail.
|
||||
p.InvokeFail(t, "invalid attribute type: 34", "getAttributeFee", int64(transaction.NotaryAssistedT))
|
||||
|
||||
for e.Chain.BlockHeight() < domovoiHeight-1 {
|
||||
e.AddNewBlock(t)
|
||||
}
|
||||
|
||||
// Invoke at Domovoi should return the default value.
|
||||
p.Invoke(t, 1000_0000, "getAttributeFee", int64(transaction.NotaryAssistedT))
|
||||
|
||||
// Invoke after Domovoi should return the default value.
|
||||
p.Invoke(t, 1000_0000, "getAttributeFee", int64(transaction.NotaryAssistedT))
|
||||
}
|
||||
|
||||
func TestPolicy_SetNotaryFeePerKey(t *testing.T) {
|
||||
const domovoiHeight = 4
|
||||
bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
|
||||
c.Hardforks = map[string]uint32{
|
||||
config.HFDomovoi.String(): domovoiHeight,
|
||||
}
|
||||
})
|
||||
e := neotest.NewExecutor(t, bc, acc, acc)
|
||||
p := e.CommitteeInvoker(nativehashes.PolicyContract)
|
||||
|
||||
// Invoke before Domovoi should fail.
|
||||
p.InvokeFail(t, "invalid attribute type: 34", "setAttributeFee", int64(transaction.NotaryAssistedT), 500_0000)
|
||||
|
||||
for e.Chain.BlockHeight() < domovoiHeight-1 {
|
||||
e.AddNewBlock(t)
|
||||
}
|
||||
|
||||
// Invoke at Domovoi should return the default value.
|
||||
p.Invoke(t, nil, "setAttributeFee", int64(transaction.NotaryAssistedT), 500_0000)
|
||||
|
||||
// Invoke after Domovoi should return the default value.
|
||||
p.Invoke(t, nil, "setAttributeFee", int64(transaction.NotaryAssistedT), 510_0000)
|
||||
}
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
package transaction
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
)
|
||||
|
||||
// NotaryAssistedActivation stores the hardfork of NotaryAssisted transaction attribute
|
||||
// activation.
|
||||
var NotaryAssistedActivation = config.HFDomovoi
|
||||
|
||||
// NotaryAssisted represents attribute for notary service transactions.
|
||||
type NotaryAssisted struct {
|
||||
NKeys uint8 `json:"nkeys"`
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mpt"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
|
@ -65,7 +66,6 @@ type (
|
|||
GetMaxVerificationGAS() int64
|
||||
GetMemPool() *mempool.Pool
|
||||
GetNotaryBalance(acc util.Uint160) *big.Int
|
||||
GetNotaryContractScriptHash() util.Uint160
|
||||
GetNotaryDepositExpiration(acc util.Uint160) uint32
|
||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||
HasBlock(util.Uint256) bool
|
||||
|
@ -1228,7 +1228,7 @@ func (s *Server) verifyNotaryRequest(_ *transaction.Transaction, data any) error
|
|||
if _, err := s.chain.VerifyWitness(payer, r, &r.Witness, s.chain.GetMaxVerificationGAS()); err != nil {
|
||||
return fmt.Errorf("bad P2PNotaryRequest payload witness: %w", err)
|
||||
}
|
||||
notaryHash := s.chain.GetNotaryContractScriptHash()
|
||||
notaryHash := nativehashes.Notary
|
||||
if r.FallbackTransaction.Sender() != notaryHash {
|
||||
return fmt.Errorf("P2PNotary contract should be a sender of the fallback transaction, got %s", address.Uint160ToString(r.FallbackTransaction.Sender()))
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mpt"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/network/capability"
|
||||
|
@ -1048,7 +1049,6 @@ func TestMemPool(t *testing.T) {
|
|||
func TestVerifyNotaryRequest(t *testing.T) {
|
||||
bc := fakechain.NewFakeChain()
|
||||
bc.MaxVerificationGAS = 10
|
||||
bc.NotaryContractScriptHash = util.Uint160{1, 2, 3}
|
||||
s, err := newServerFromConstructors(ServerConfig{Addresses: []config.AnnounceableAddress{{Address: ":0"}}}, bc, new(fakechain.FakeStateSync), zaptest.NewLogger(t), newFakeTransp, newTestDiscovery)
|
||||
require.NoError(t, err)
|
||||
newNotaryRequest := func() *payload.P2PNotaryRequest {
|
||||
|
@ -1059,7 +1059,7 @@ func TestVerifyNotaryRequest(t *testing.T) {
|
|||
},
|
||||
FallbackTransaction: &transaction.Transaction{
|
||||
ValidUntilBlock: 321,
|
||||
Signers: []transaction.Signer{{Account: bc.NotaryContractScriptHash}, {Account: random.Uint160()}},
|
||||
Signers: []transaction.Signer{{Account: nativehashes.Notary}, {Account: random.Uint160()}},
|
||||
},
|
||||
Witness: transaction.Witness{},
|
||||
}
|
||||
|
@ -1080,7 +1080,7 @@ func TestVerifyNotaryRequest(t *testing.T) {
|
|||
t.Run("bad main sender", func(t *testing.T) {
|
||||
bc.VerifyWitnessF = func() (int64, error) { return 0, nil }
|
||||
r := newNotaryRequest()
|
||||
r.MainTransaction.Signers[0] = transaction.Signer{Account: bc.NotaryContractScriptHash}
|
||||
r.MainTransaction.Signers[0] = transaction.Signer{Account: nativehashes.Notary}
|
||||
require.Error(t, s.verifyNotaryRequest(nil, r))
|
||||
})
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
|
@ -171,7 +172,7 @@ func TestNotary(t *testing.T) {
|
|||
fallback.ValidUntilBlock = bc.BlockHeight() + 2*nvbDiffFallback
|
||||
fallback.Signers = []transaction.Signer{
|
||||
{
|
||||
Account: bc.GetNotaryContractScriptHash(),
|
||||
Account: nativehashes.Notary,
|
||||
Scopes: transaction.None,
|
||||
},
|
||||
{
|
||||
|
@ -240,7 +241,7 @@ func TestNotary(t *testing.T) {
|
|||
verificationScripts = append(verificationScripts, script)
|
||||
}
|
||||
signers[len(signers)-1] = transaction.Signer{
|
||||
Account: bc.GetNotaryContractScriptHash(),
|
||||
Account: nativehashes.Notary,
|
||||
Scopes: transaction.None,
|
||||
}
|
||||
mainTx.Signers = signers
|
||||
|
@ -752,9 +753,9 @@ func TestNotary(t *testing.T) {
|
|||
requester1, _ := wallet.NewAccount()
|
||||
requester2, _ := wallet.NewAccount()
|
||||
amount := int64(100_0000_0000)
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []any{requester1.ScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), nativehashes.Notary, amount, []any{requester1.ScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
e.CheckGASBalance(t, notaryHash, big.NewInt(amount))
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), bc.GetNotaryContractScriptHash(), amount, []any{requester2.ScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
gasValidatorInvoker.Invoke(t, true, "transfer", e.Validator.ScriptHash(), nativehashes.Notary, amount, []any{requester2.ScriptHash(), int64(bc.BlockHeight() + 50)})
|
||||
e.CheckGASBalance(t, notaryHash, big.NewInt(2*amount))
|
||||
|
||||
// create request for 2 standard signatures => main tx should be completed after the second request is added to the pool
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempoolevent"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
|
@ -31,7 +32,6 @@ type (
|
|||
Ledger interface {
|
||||
BlockHeight() uint32
|
||||
GetMaxVerificationGAS() int64
|
||||
GetNotaryContractScriptHash() util.Uint160
|
||||
SubscribeForBlocks(ch chan *block.Block)
|
||||
UnsubscribeFromBlocks(ch chan *block.Block)
|
||||
VerifyWitness(util.Uint160, hash.Hashable, *transaction.Witness, int64) (int64, error)
|
||||
|
@ -408,7 +408,7 @@ func (n *Notary) finalize(acc *wallet.Account, tx *transaction.Transaction, h ut
|
|||
VerificationScript: []byte{},
|
||||
}
|
||||
for i, signer := range tx.Signers {
|
||||
if signer.Account == n.Config.Chain.GetNotaryContractScriptHash() {
|
||||
if signer.Account == nativehashes.Notary {
|
||||
tx.Scripts[i] = notaryWitness
|
||||
break
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ func (n *Notary) verifyIncompleteWitnesses(tx *transaction.Transaction, nKeysExp
|
|||
if len(tx.Signers) < 2 {
|
||||
return nil, errors.New("transaction should have at least 2 signers")
|
||||
}
|
||||
if !tx.HasSigner(n.Config.Chain.GetNotaryContractScriptHash()) {
|
||||
if !tx.HasSigner(nativehashes.Notary) {
|
||||
return nil, fmt.Errorf("P2PNotary contract should be a signer of the transaction")
|
||||
}
|
||||
result := make([]witnessInfo, len(tx.Signers))
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/mempool"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
@ -48,8 +48,7 @@ func TestWallet(t *testing.T) {
|
|||
|
||||
func TestVerifyIncompleteRequest(t *testing.T) {
|
||||
bc := fakechain.NewFakeChain()
|
||||
notaryContractHash := util.Uint160{1, 2, 3}
|
||||
bc.NotaryContractScriptHash = notaryContractHash
|
||||
notaryContractHash := nativehashes.Notary
|
||||
_, ntr, _ := getTestNotary(t, bc, "./testdata/notary1.json", "one")
|
||||
sig := append([]byte{byte(opcode.PUSHDATA1), keys.SignatureLen}, make([]byte, keys.SignatureLen)...) // we're not interested in signature correctness
|
||||
acc1, _ := keys.NewPrivateKey()
|
||||
|
|
|
@ -465,6 +465,10 @@ func TestClientNEOContract(t *testing.T) {
|
|||
func TestClientNotary(t *testing.T) {
|
||||
chain, _, httpSrv := initServerWithInMemoryChain(t)
|
||||
|
||||
// Domovoi should be enabled since this test uses Notary contract.
|
||||
_, ok := chain.GetConfig().Hardforks[config.HFDomovoi.String()]
|
||||
require.True(t, ok)
|
||||
|
||||
c, err := rpcclient.New(context.Background(), httpSrv.URL, rpcclient.Options{})
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(c.Close)
|
||||
|
@ -2446,7 +2450,10 @@ func TestClient_GetVersion_Hardforks(t *testing.T) {
|
|||
v, err := c.GetVersion()
|
||||
require.NoError(t, err)
|
||||
expected := map[config.Hardfork]uint32{
|
||||
config.HFAspidochelone: 25,
|
||||
config.HFAspidochelone: 0,
|
||||
config.HFBasilisk: 0,
|
||||
config.HFCockatrice: 0,
|
||||
config.HFDomovoi: 0,
|
||||
}
|
||||
require.InDeltaMapValues(t, expected, v.Protocol.Hardforks, 0)
|
||||
}
|
||||
|
|
|
@ -88,7 +88,6 @@ type (
|
|||
GetNativeContractScriptHash(string) (util.Uint160, error)
|
||||
GetNatives() []state.Contract
|
||||
GetNextBlockValidators() ([]*keys.PublicKey, error)
|
||||
GetNotaryContractScriptHash() util.Uint160
|
||||
GetStateModule() core.StateRoot
|
||||
GetStorageItem(id int32, key []byte) state.StorageItem
|
||||
GetTestHistoricVM(t trigger.Type, tx *transaction.Transaction, nextBlockHeight uint32) (*interop.Context, error)
|
||||
|
|
|
@ -54,6 +54,7 @@ func getUnitTestChain(t testing.TB, enableOracle bool, enableNotary bool, disabl
|
|||
Password: "one",
|
||||
}
|
||||
}
|
||||
cfg.ProtocolConfiguration.Hardforks = nil
|
||||
})
|
||||
}
|
||||
func getUnitTestChainWithCustomConfig(t testing.TB, enableOracle bool, enableNotary bool, customCfg func(configuration *config.Config)) (*core.Blockchain, OracleHandler, config.Config, *zap.Logger) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/interopnames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativehashes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage/dboper"
|
||||
|
@ -74,22 +75,22 @@ type rpcTestCase struct {
|
|||
}
|
||||
|
||||
const genesisBlockHash = "0f8fb4e17d2ab9f3097af75ca7fd16064160fb8043db94909e00dd4e257b9dc4"
|
||||
const testContractHash = "565cff9508ebc75aadd7fe59f38dac610ab6093c"
|
||||
const deploymentTxHash = "a14390941cc3a1d87393eff720a722e9cd350bd6ed233c5fe2001326c80eb68e"
|
||||
const testContractHash = "449fe8fbd4523072f5e3a4dfa17a494c119d4c08"
|
||||
const deploymentTxHash = "af170742f0f8a2bc064bdbdb2faa2b517e3df833d4d047da8a946c0b8d581b06"
|
||||
|
||||
const (
|
||||
verifyContractHash = "06ed5314c2e4cb103029a60b86d46afa2fb8f67c"
|
||||
verifyContractAVM = "VwIAQS1RCDBwDBTunqIsJ+NL0BSPxBCOCPdOj1BIskrZMCQE2zBxaBPOStkoJATbKGlK2SgkBNsol0A="
|
||||
verifyWithArgsContractHash = "4dc916254efd2947c93b11207e8ffc0bb56161c5"
|
||||
nnsContractHash = "892429fcd47c30f8451781acc627e8b20e0d64f3"
|
||||
verifyWithArgsContractHash = "6261b3bf753bdc3d24c1327a23fd891e1c8a7ccd"
|
||||
nnsContractHash = "ebe47d5143bb8726b87b02efb5cd98e21174fd38"
|
||||
nnsToken1ID = "6e656f2e636f6d"
|
||||
nfsoContractHash = "730ebe719ab8e3b69d11dafc95cdb9bf409db179"
|
||||
nfsoContractHash = "2f5c1826bb4da1c764a8871427e4044cf3e82dbd"
|
||||
nfsoToken1ID = "7e244ffd6aa85fb1579d2ed22e9b761ab62e3486"
|
||||
storageContractHash = "ebc0c16a76c808cd4dde6bcc063f09e45e331ec7"
|
||||
faultedTxHashLE = "82279bfe9bada282ca0f8cb8e0bb124b921af36f00c69a518320322c6f4fef60"
|
||||
faultedTxBlock uint32 = 23
|
||||
invokescriptContractAVM = "VwIADBQBDAMOBQYMDQIODw0DDgcJAAAAAErZMCQE2zBwaEH4J+yMqiYEEUAMFA0PAwIJAAIBAwcDBAUCAQAOBgwJStkwJATbMHFpQfgn7IyqJgQSQBNA"
|
||||
block20StateRootLE = "858c873539d6d24a70f2be13f9dafc61aef2b63c2aa16bb440676de6e44e3cf1"
|
||||
block20StateRootLE = "b49a35fd3a749fc2f7f4e5fe1f288ef2b6188416f65fe5b691892e8209092082"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -1381,7 +1382,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52)
|
||||
return &result.Invoke{
|
||||
State: "HALT",
|
||||
GasConsumed: 31922970,
|
||||
GasConsumed: 31922730,
|
||||
Script: script,
|
||||
Stack: []stackitem.Item{stackitem.Make(true)},
|
||||
Notifications: []state.NotificationEvent{{
|
||||
|
@ -1411,7 +1412,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
chg := []dboper.Operation{{
|
||||
State: "Changed",
|
||||
Key: []byte{0xfa, 0xff, 0xff, 0xff, 0xb},
|
||||
Value: []byte{0x54, 0xb2, 0xd2, 0xa3, 0x51, 0x79, 0x12},
|
||||
Value: []byte{0x06, 0x44, 0xda, 0xa3, 0x51, 0x79, 0x12},
|
||||
}, {
|
||||
State: "Added",
|
||||
Key: []byte{0xfb, 0xff, 0xff, 0xff, 0x14, 0xd6, 0x24, 0x87, 0x12, 0xff, 0x97, 0x22, 0x80, 0xa0, 0xae, 0xf5, 0x24, 0x1c, 0x96, 0x4d, 0x63, 0x78, 0x29, 0xcd, 0xb},
|
||||
|
@ -1423,7 +1424,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
}, {
|
||||
State: "Changed",
|
||||
Key: []byte{0xfa, 0xff, 0xff, 0xff, 0x14, 0xee, 0x9e, 0xa2, 0x2c, 0x27, 0xe3, 0x4b, 0xd0, 0x14, 0x8f, 0xc4, 0x10, 0x8e, 0x8, 0xf7, 0x4e, 0x8f, 0x50, 0x48, 0xb2},
|
||||
Value: []byte{0x41, 0x01, 0x21, 0x05, 0x0c, 0x76, 0x4f, 0xdf, 0x08},
|
||||
Value: []byte{0x41, 0x01, 0x21, 0x05, 0xf6, 0x64, 0x58, 0xdf, 0x08},
|
||||
}}
|
||||
// Can be returned in any order.
|
||||
assert.ElementsMatch(t, chg, res.Diagnostics.Changes)
|
||||
|
@ -1439,7 +1440,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
cryptoHash, _ := e.chain.GetNativeContractScriptHash(nativenames.CryptoLib)
|
||||
return &result.Invoke{
|
||||
State: "HALT",
|
||||
GasConsumed: 13970250,
|
||||
GasConsumed: 13969530,
|
||||
Script: script,
|
||||
Stack: []stackitem.Item{stackitem.Make("1.2.3.4")},
|
||||
Notifications: []state.NotificationEvent{},
|
||||
|
@ -1532,7 +1533,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
script = append(script, 0x41, 0x62, 0x7d, 0x5b, 0x52)
|
||||
return &result.Invoke{
|
||||
State: "HALT",
|
||||
GasConsumed: 31922970,
|
||||
GasConsumed: 31922730,
|
||||
Script: script,
|
||||
Stack: []stackitem.Item{stackitem.Make(true)},
|
||||
Notifications: []state.NotificationEvent{{
|
||||
|
@ -1558,7 +1559,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
|||
cryptoHash, _ := e.chain.GetNativeContractScriptHash(nativenames.CryptoLib)
|
||||
return &result.Invoke{
|
||||
State: "HALT",
|
||||
GasConsumed: 13970250,
|
||||
GasConsumed: 13969530,
|
||||
Script: script,
|
||||
Stack: []stackitem.Item{stackitem.Make("1.2.3.4")},
|
||||
Notifications: []state.NotificationEvent{},
|
||||
|
@ -2495,7 +2496,7 @@ func createValidNotaryRequest(chain *core.Blockchain, sender *keys.PrivateKey, n
|
|||
{Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: mainTx.Hash()}},
|
||||
{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 0}},
|
||||
},
|
||||
Signers: []transaction.Signer{{Account: chain.GetNotaryContractScriptHash()}, {Account: sender.GetScriptHash()}},
|
||||
Signers: []transaction.Signer{{Account: nativehashes.Notary}, {Account: sender.GetScriptHash()}},
|
||||
Scripts: []transaction.Witness{
|
||||
{InvocationScript: append([]byte{byte(opcode.PUSHDATA1), keys.SignatureLen}, make([]byte, keys.SignatureLen)...), VerificationScript: []byte{}},
|
||||
},
|
||||
|
@ -3260,7 +3261,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
|||
t.Run("contract-based verification with parameters", func(t *testing.T) {
|
||||
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
||||
require.NoError(t, err)
|
||||
checkContract(t, verAcc, []byte{}, 244130) // No C# match, but we believe it's OK and it differs from the one above.
|
||||
checkContract(t, verAcc, []byte{}, 244010) // No C# match, but we believe it's OK and it differs from the one above.
|
||||
})
|
||||
t.Run("contract-based verification with invocation script", func(t *testing.T) {
|
||||
verAcc, err := util.Uint160DecodeStringLE(verifyWithArgsContractHash)
|
||||
|
@ -3270,7 +3271,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) []
|
|||
emit.Int(invocWriter.BinWriter, 5)
|
||||
emit.String(invocWriter.BinWriter, "")
|
||||
invocScript := invocWriter.Bytes()
|
||||
checkContract(t, verAcc, invocScript, 146960) // No C# match, but we believe it's OK and it has a specific invocation script overriding anything server-side.
|
||||
checkContract(t, verAcc, invocScript, 146840) // No C# match, but we believe it's OK and it has a specific invocation script overriding anything server-side.
|
||||
})
|
||||
t.Run("execution limit, ok", func(t *testing.T) {
|
||||
// 1_4000_0000 GAS with the default 1.5 allowed by Policy
|
||||
|
@ -3575,7 +3576,7 @@ func checkNep17Balances(t *testing.T, e *executor, acc any) {
|
|||
},
|
||||
{
|
||||
Asset: e.chain.UtilityTokenHash(),
|
||||
Amount: "37106285100",
|
||||
Amount: "37106870550",
|
||||
LastUpdated: 23,
|
||||
Decimals: 8,
|
||||
Name: "GasToken",
|
||||
|
@ -3924,7 +3925,7 @@ func checkNep17TransfersAux(t *testing.T, e *executor, acc any, sent, rcvd []int
|
|||
{
|
||||
Timestamp: blockDepositGAS.Timestamp,
|
||||
Asset: e.chain.UtilityTokenHash(),
|
||||
Address: address.Uint160ToString(e.chain.GetNotaryContractScriptHash()),
|
||||
Address: address.Uint160ToString(nativehashes.Notary),
|
||||
Amount: "1000000000",
|
||||
Index: 8,
|
||||
NotifyIndex: 0,
|
||||
|
|
BIN
pkg/services/rpcsrv/testdata/testblocks.acc
vendored
BIN
pkg/services/rpcsrv/testdata/testblocks.acc
vendored
Binary file not shown.
Loading…
Reference in a new issue