Skip to content

Commit

Permalink
core, rpcsrv: apply generic attributes fee logic to NotaryServiceFeeP…
Browse files Browse the repository at this point in the history
…erKey

Remove related methods from native Notary and add relevant code to native
Policy.

Signed-off-by: Anna Shaleva <[email protected]>
  • Loading branch information
AnnaShaleva committed Sep 22, 2023
1 parent 8c4f978 commit a33d3f3
Show file tree
Hide file tree
Showing 15 changed files with 90 additions and 145 deletions.
12 changes: 11 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,14 @@ NeoGo retains certain deprecated error codes: `neorpc.ErrCompatGeneric`,
`neorpc.ErrCompatNoOpenedWallet`. They returned by nodes not compliant with the
neo-project/proposals#156 (NeoGo pre-0.102.0 and all known C# versions).

Removal of the deprecated RPC error codes is planned once all nodes adopt the new error standard.
Removal of the deprecated RPC error codes is planned once all nodes adopt the new error standard.

## NotaryServiceFeePerKey native Notary contract functionality removal

`getNotaryServiceFeePerKey` and `setNotaryServiceFeePerKey` methods were moved from
native Notary contract to the native PolicyContract contract to be a part of more
generic attribute fees functionality (`getAttributeFee` and `setAttributeFee`
methods for the NotaryAssisted attribute).

Removal of the related Notary-specific interop APIs and RPC Client Actor APIs
is scheduled for Jan-Feb 2024 (~0.106.0 release).
2 changes: 0 additions & 2 deletions pkg/compiler/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,6 @@ func TestNativeHelpersCompile(t *testing.T) {
{"expirationOf", []string{u160}},
{"getMaxNotValidBeforeDelta", nil},
{"setMaxNotValidBeforeDelta", []string{"42"}},
{"getNotaryServiceFeePerKey", nil},
{"setNotaryServiceFeePerKey", []string{"42"}},
})
runNativeTestCases(t, cs.Management.ContractMD, "management", []nativeTestCase{
{"deploy", []string{"nil", "nil"}},
Expand Down
25 changes: 8 additions & 17 deletions pkg/core/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -2060,10 +2060,10 @@ func (bc *Blockchain) GetNotaryBalance(acc util.Uint160) *big.Int {
return bc.contracts.Notary.BalanceOf(bc.dao, acc)
}

// GetNotaryServiceFeePerKey returns NotaryServiceFeePerKey which is a reward per
// notary request key for designated notary nodes.
// GetNotaryServiceFeePerKey returns a NotaryAssisted transaction attribute fee
// per key which is a reward per notary request key for designated notary nodes.
func (bc *Blockchain) GetNotaryServiceFeePerKey() int64 {
return bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
return bc.contracts.Policy.GetAttributeFeeInternal(bc.dao, transaction.NotaryAssistedT)
}

// GetNotaryContractScriptHash returns Notary native contract hash.
Expand Down Expand Up @@ -2486,13 +2486,6 @@ func (bc *Blockchain) verifyAndPoolTx(t *transaction.Transaction, pool *mempool.
return fmt.Errorf("%w: (%d > MaxTransactionSize %d)", ErrTxTooBig, size, transaction.MaxTransactionSize)
}
needNetworkFee := int64(size)*bc.FeePerByte() + bc.CalculateAttributesFee(t)
if bc.P2PSigExtensionsEnabled() {
attrs := t.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
needNetworkFee += (int64(na.NKeys) + 1) * bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
}
}
netFee := t.NetworkFee - needNetworkFee
if netFee < 0 {
return fmt.Errorf("%w: net fee is %v, need %v", ErrTxSmallNetworkFee, t.NetworkFee, needNetworkFee)
Expand Down Expand Up @@ -2555,6 +2548,11 @@ func (bc *Blockchain) CalculateAttributesFee(tx *transaction.Transaction) int64
switch attr.Type {
case transaction.ConflictsT:
feeSum += base * int64(len(tx.Signers))
case transaction.NotaryAssistedT:
if bc.P2PSigExtensionsEnabled() {
na := attr.Value.(*transaction.NotaryAssisted)
feeSum += base * (int64(na.NKeys) + 1)
}
default:
feeSum += base
}
Expand Down Expand Up @@ -2919,13 +2917,6 @@ func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block
var gasLimit int64
if len(verificationFee) == 0 {
gasLimit = t.NetworkFee - int64(t.Size())*bc.FeePerByte() - bc.CalculateAttributesFee(t)
if bc.P2PSigExtensionsEnabled() {
attrs := t.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
gasLimit -= (int64(na.NKeys) + 1) * bc.contracts.Notary.GetNotaryServiceFeePerKey(bc.dao)
}
}
} else {
gasLimit = verificationFee[0]
}
Expand Down
5 changes: 3 additions & 2 deletions pkg/core/native/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {

gas := newGAS(int64(cfg.InitialGASSupply), cfg.P2PSigExtensions)
neo := newNEO(cfg)
policy := newPolicy()
policy := newPolicy(cfg.P2PSigExtensions)
neo.GAS = gas
neo.Policy = policy
gas.NEO = neo
gas.Policy = policy
mgmt.NEO = neo
mgmt.Policy = policy
policy.NEO = neo
Expand All @@ -104,8 +105,8 @@ func NewContracts(cfg config.ProtocolConfiguration) *Contracts {
notary.GAS = gas
notary.NEO = neo
notary.Desig = desig
notary.Policy = policy
cs.Notary = notary
gas.Notary = notary
cs.Contracts = append(cs.Contracts, notary)
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/core/native/management_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

func TestDeployGetUpdateDestroyContract(t *testing.T) {
mgmt := newManagement()
mgmt.Policy = newPolicy()
mgmt.Policy = newPolicy(false)
d := dao.NewSimple(storage.NewMemoryStore(), false)
ic := &interop.Context{DAO: d}
err := mgmt.Initialize(ic)
Expand Down Expand Up @@ -97,7 +97,7 @@ func TestManagement_Initialize(t *testing.T) {

func TestManagement_GetNEP17Contracts(t *testing.T) {
mgmt := newManagement()
mgmt.Policy = newPolicy()
mgmt.Policy = newPolicy(false)
d := dao.NewSimple(storage.NewMemoryStore(), false)
err := mgmt.Initialize(&interop.Context{DAO: d})
require.NoError(t, err)
Expand Down
7 changes: 3 additions & 4 deletions pkg/core/native/native_gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ import (
// GAS represents GAS native contract.
type GAS struct {
nep17TokenNative
NEO *NEO
// Notary is a native Notary contract. It is set only when P2PSigExtensions are on.
Notary *Notary
NEO *NEO
Policy *Policy

initialSupply int64
p2pSigExtensionsEnabled bool
Expand Down Expand Up @@ -124,7 +123,7 @@ func (g *GAS) OnPersist(ic *interop.Context) error {
attrs := tx.GetAttributes(transaction.NotaryAssistedT)
if len(attrs) != 0 {
na := attrs[0].Value.(*transaction.NotaryAssisted)
netFee -= (int64(na.NKeys) + 1) * g.Notary.GetNotaryServiceFeePerKey(ic.DAO)
netFee -= (int64(na.NKeys) + 1) * g.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
}
}
}
Expand Down
10 changes: 0 additions & 10 deletions pkg/core/native/native_test/notary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,6 @@ func TestNotary_MaxNotValidBeforeDeltaCache(t *testing.T) {
testGetSetCache(t, c, "MaxNotValidBeforeDelta", 140)
}

func TestNotary_NotaryServiceFeePerKey(t *testing.T) {
c := newNotaryClient(t)
testGetSet(t, c, "NotaryServiceFeePerKey", 1000_0000, 0, 0)
}

func TestNotary_NotaryServiceFeePerKeyCache(t *testing.T) {
c := newNotaryClient(t)
testGetSetCache(t, c, "NotaryServiceFeePerKey", 1000_0000)
}

func TestNotary_Pipeline(t *testing.T) {
notaryCommitteeInvoker := newNotaryClient(t)
e := notaryCommitteeInvoker.Executor
Expand Down
59 changes: 8 additions & 51 deletions pkg/core/native/notary.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ import (
// Notary represents Notary native contract.
type Notary struct {
interop.ContractMD
GAS *GAS
NEO *NEO
Desig *Designate
GAS *GAS
NEO *NEO
Desig *Designate
Policy *Policy
}

type NotaryCache struct {
maxNotValidBeforeDelta uint32
notaryServiceFeePerKey int64
}

// NotaryService is a Notary module interface.
Expand All @@ -48,15 +48,10 @@ const (
// prefixDeposit is a prefix for storing Notary deposits.
prefixDeposit = 1
defaultDepositDeltaTill = 5760
defaultMaxNotValidBeforeDelta = 140 // 20 rounds for 7 validators, a little more than half an hour
defaultNotaryServiceFeePerKey = 1000_0000 // 0.1 GAS
maxNotaryServiceFeePerKey = 1_0000_0000 // 1 GAS
defaultMaxNotValidBeforeDelta = 140 // 20 rounds for 7 validators, a little more than half an hour
)

var (
maxNotValidBeforeDeltaKey = []byte{10}
notaryServiceFeeKey = []byte{5}
)
var maxNotValidBeforeDeltaKey = []byte{10}

var (
_ interop.Contract = (*Notary)(nil)
Expand Down Expand Up @@ -122,15 +117,6 @@ func newNotary() *Notary {
md = newMethodAndPrice(n.setMaxNotValidBeforeDelta, 1<<15, callflag.States)
n.AddMethod(md, desc)

desc = newDescriptor("getNotaryServiceFeePerKey", smartcontract.IntegerType)
md = newMethodAndPrice(n.getNotaryServiceFeePerKey, 1<<15, callflag.ReadStates)
n.AddMethod(md, desc)

desc = newDescriptor("setNotaryServiceFeePerKey", smartcontract.VoidType,
manifest.NewParameter("value", smartcontract.IntegerType))
md = newMethodAndPrice(n.setNotaryServiceFeePerKey, 1<<15, callflag.States)
n.AddMethod(md, desc)

return n
}

Expand All @@ -142,11 +128,9 @@ func (n *Notary) Metadata() *interop.ContractMD {
// Initialize initializes Notary native contract and implements the Contract interface.
func (n *Notary) Initialize(ic *interop.Context) error {
setIntWithKey(n.ID, ic.DAO, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta)
setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, defaultNotaryServiceFeePerKey)

cache := &NotaryCache{
maxNotValidBeforeDelta: defaultMaxNotValidBeforeDelta,
notaryServiceFeePerKey: defaultNotaryServiceFeePerKey,
}
ic.DAO.SetCache(n.ID, cache)
return nil
Expand All @@ -155,7 +139,6 @@ func (n *Notary) Initialize(ic *interop.Context) error {
func (n *Notary) InitializeCache(blockHeight uint32, d *dao.Simple) error {
cache := &NotaryCache{
maxNotValidBeforeDelta: uint32(getIntWithKey(n.ID, d, maxNotValidBeforeDeltaKey)),
notaryServiceFeePerKey: getIntWithKey(n.ID, d, notaryServiceFeeKey),
}

d.SetCache(n.ID, cache)
Expand Down Expand Up @@ -197,7 +180,7 @@ func (n *Notary) OnPersist(ic *interop.Context) error {
if nFees == 0 {
return nil
}
feePerKey := n.GetNotaryServiceFeePerKey(ic.DAO)
feePerKey := n.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
singleReward := calculateNotaryReward(nFees, feePerKey, len(notaries))
for _, notary := range notaries {
n.GAS.mint(ic, notary.GetScriptHash(), singleReward, false)
Expand Down Expand Up @@ -238,7 +221,7 @@ func (n *Notary) onPayment(ic *interop.Context, args []stackitem.Item) stackitem
if deposit != nil && till < deposit.Till {
panic(fmt.Errorf("`till` shouldn't be less then the previous value %d", deposit.Till))
}
feePerKey := n.GetNotaryServiceFeePerKey(ic.DAO)
feePerKey := n.Policy.GetAttributeFeeInternal(ic.DAO, transaction.NotaryAssistedT)
if deposit == nil {
if amount.Cmp(big.NewInt(2*feePerKey)) < 0 {
panic(fmt.Errorf("first deposit can not be less then %d, got %d", 2*feePerKey, amount.Int64()))
Expand Down Expand Up @@ -434,32 +417,6 @@ func (n *Notary) setMaxNotValidBeforeDelta(ic *interop.Context, args []stackitem
return stackitem.Null{}
}

// getNotaryServiceFeePerKey is a Notary contract method and returns a reward per notary request key for notary nodes.
func (n *Notary) getNotaryServiceFeePerKey(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
return stackitem.NewBigInteger(big.NewInt(int64(n.GetNotaryServiceFeePerKey(ic.DAO))))
}

// GetNotaryServiceFeePerKey is an internal representation of Notary getNotaryServiceFeePerKey method.
func (n *Notary) GetNotaryServiceFeePerKey(dao *dao.Simple) int64 {
cache := dao.GetROCache(n.ID).(*NotaryCache)
return cache.notaryServiceFeePerKey
}

// setNotaryServiceFeePerKey is a Notary contract method and sets a reward per notary request key for notary nodes.
func (n *Notary) setNotaryServiceFeePerKey(ic *interop.Context, args []stackitem.Item) stackitem.Item {
value := toInt64(args[0])
if value < 0 || value > maxNotaryServiceFeePerKey {
panic("NotaryServiceFeePerKey value is out of range")
}
if !n.NEO.checkCommittee(ic) {
panic("invalid committee signature")
}
setIntWithKey(n.ID, ic.DAO, notaryServiceFeeKey, int64(value))
cache := ic.DAO.GetRWCache(n.ID).(*NotaryCache)
cache.notaryServiceFeePerKey = value
return stackitem.Null{}
}

// GetDepositFor returns state.Deposit for the account specified. It returns nil in case
// the deposit is not found in the storage and panics in case of any other error.
func (n *Notary) GetDepositFor(dao *dao.Simple, acc util.Uint160) *state.Deposit {
Expand Down
16 changes: 14 additions & 2 deletions pkg/core/native/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const (
defaultMaxVerificationGas = 1_50000000
// defaultAttributeFee is a default fee for a transaction attribute those price wasn't set yet.
defaultAttributeFee = 0
// defaultNotaryAssistedFee is a default fee for a NotaryAssisted transaction attribute per key.
defaultNotaryAssistedFee = 1000_0000 // 0.1 GAS
// DefaultStoragePrice is the price to pay for 1 byte of storage.
DefaultStoragePrice = 100000

Expand Down Expand Up @@ -60,6 +62,9 @@ var (
type Policy struct {
interop.ContractMD
NEO *NEO

// p2pSigExtensionsEnabled defines whether the P2P signature extensions logic is relevant.
p2pSigExtensionsEnabled bool
}

type PolicyCache struct {
Expand Down Expand Up @@ -94,8 +99,11 @@ func copyPolicyCache(src, dst *PolicyCache) {
}

// newPolicy returns Policy native contract.
func newPolicy() *Policy {
p := &Policy{ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID)}
func newPolicy(p2pSigExtensionsEnabled bool) *Policy {
p := &Policy{
ContractMD: *interop.NewContractMD(nativenames.Policy, policyContractID),
p2pSigExtensionsEnabled: p2pSigExtensionsEnabled,
}
defer p.UpdateHash()

desc := newDescriptor("getFeePerByte", smartcontract.IntegerType)
Expand Down Expand Up @@ -173,6 +181,10 @@ func (p *Policy) Initialize(ic *interop.Context) error {
attributeFee: map[transaction.AttrType]uint32{},
blockedAccounts: make([]util.Uint160, 0),
}
if p.p2pSigExtensionsEnabled {
setIntWithKey(p.ID, ic.DAO, []byte{attributeFeePrefix, byte(transaction.NotaryAssistedT)}, defaultNotaryAssistedFee)
cache.attributeFee[transaction.NotaryAssistedT] = defaultNotaryAssistedFee
}
ic.DAO.SetCache(p.ID, cache)

return nil
Expand Down
8 changes: 8 additions & 0 deletions pkg/interop/native/notary/notary.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,19 @@ func SetMaxNotValidBeforeDelta(value int) {
}

// GetNotaryServiceFeePerKey represents `getNotaryServiceFeePerKey` method of Notary native contract.
//
// Deprecated: this logic has been moved to native Policy contract since 0.102.1.
// Please, use policy.GetAttributeFee(NotaryAssistedT) instead, this method will
// be removed in future versions.
func GetNotaryServiceFeePerKey() int {
return neogointernal.CallWithToken(Hash, "getNotaryServiceFeePerKey", int(contract.ReadStates)).(int)
}

// SetNotaryServiceFeePerKey represents `setNotaryServiceFeePerKey` method of Notary native contract.
//
// Deprecated: this logic has been moved to native Policy contract since 0.102.1.
// Please, use policy.SetAttributeFee(NotaryAssistedT, value) instead, this method
// will be removed in future versions.
func SetNotaryServiceFeePerKey(value int) {
neogointernal.CallWithTokenNoRet(Hash, "setNotaryServiceFeePerKey", int(contract.States), value)
}
16 changes: 16 additions & 0 deletions pkg/rpcclient/notary/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ func (c *ContractReader) GetMaxNotValidBeforeDelta() (uint32, error) {

// GetNotaryServiceFeePerKey returns the per-key fee amount paid by transactions
// for the NotaryAssisted attribute.
//
// Deprecated: this logic has been moved to native Policy contract since 0.102.1.
// Please, use policy.GetAttributeFee(NotaryAssistedT) instead, this method will
// be removed in future versions.
func (c *ContractReader) GetNotaryServiceFeePerKey() (int64, error) {
return unwrap.Int64(c.invoker.Call(Hash, "getNotaryServiceFeePerKey"))
}
Expand Down Expand Up @@ -187,6 +191,10 @@ func (c *Contract) SetMaxNotValidBeforeDeltaUnsigned(blocks uint32) (*transactio
// when transaction ends in HALT state. Notice that this setting can be changed
// only by the network's committee, so use an appropriate Actor. The returned
// values are transaction hash, its ValidUntilBlock value and an error if any.
//
// Deprecated: this logic has been moved to native Policy contract since 0.102.1.
// Please, use policy.SetAttributeFee(NotaryAssistedT, fee) instead, this method
// will be removed in future versions.
func (c *Contract) SetNotaryServiceFeePerKey(fee int64) (util.Uint256, uint32, error) {
return c.actor.SendCall(Hash, setFeePKMethod, fee)
}
Expand All @@ -196,6 +204,10 @@ func (c *Contract) SetNotaryServiceFeePerKey(fee int64) (util.Uint256, uint32, e
// when transaction ends in HALT state. Notice that this setting can be changed
// only by the network's committee, so use an appropriate Actor. The transaction
// is signed, but not sent to the network, instead it's returned to the caller.
//
// Deprecated: this logic has been moved to native Policy contract since 0.102.1.
// Please, use policy.SetAttributeFeeTransaction(NotaryAssistedT, fee) instead,
// this method will be removed in future versions.
func (c *Contract) SetNotaryServiceFeePerKeyTransaction(fee int64) (*transaction.Transaction, error) {
return c.actor.MakeCall(Hash, setFeePKMethod, fee)
}
Expand All @@ -205,6 +217,10 @@ func (c *Contract) SetNotaryServiceFeePerKeyTransaction(fee int64) (*transaction
// when transaction ends in HALT state. Notice that this setting can be changed
// only by the network's committee, so use an appropriate Actor. The transaction
// is not signed and just returned to the caller.
//
// Deprecated: this logic has been moved to native Policy contract since 0.102.1.
// Please, use policy.SetAttributeFeeUnsigned(NotaryAssistedT, fee) instead, this
// method will be removed in future versions.
func (c *Contract) SetNotaryServiceFeePerKeyUnsigned(fee int64) (*transaction.Transaction, error) {
return c.actor.MakeUnsignedCall(Hash, setFeePKMethod, nil, fee)
}
Expand Down
Loading

0 comments on commit a33d3f3

Please sign in to comment.