diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index 65c43b1f5..3243f4a1d 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -12,6 +12,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/interop" + "github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -200,7 +201,7 @@ func TestAppCall(t *testing.T) { } fc := fakechain.NewFakeChain() - ic := interop.NewContext(trigger.Application, fc, dao.NewSimple(storage.NewMemoryStore(), false, false), interop.DefaultBaseExecFee, contractGetter, nil, nil, nil, zaptest.NewLogger(t)) + ic := interop.NewContext(trigger.Application, fc, dao.NewSimple(storage.NewMemoryStore(), false, false), interop.DefaultBaseExecFee, native.DefaultStoragePrice, contractGetter, nil, nil, nil, zaptest.NewLogger(t)) t.Run("valid script", func(t *testing.T) { src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE())) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 926e612de..19045208f 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2305,13 +2305,18 @@ func (bc *Blockchain) ManagementContractHash() util.Uint160 { func (bc *Blockchain) newInteropContext(trigger trigger.Type, d *dao.Simple, block *block.Block, tx *transaction.Transaction) *interop.Context { baseExecFee := int64(interop.DefaultBaseExecFee) - if block == nil || block.Index != 0 { // Use provided dao instead of Blockchain's one to fetch possible ExecFeeFactor // changes that were not yet persisted to Blockchain's dao. baseExecFee = bc.contracts.Policy.GetExecFeeFactorInternal(d) } - ic := interop.NewContext(trigger, bc, d, baseExecFee, bc.contracts.Management.GetContract, bc.contracts.Contracts, block, tx, bc.log) + baseStorageFee := int64(native.DefaultStoragePrice) + if block == nil || block.Index != 0 { + // Use provided dao instead of Blockchain's one to fetch possible StoragePrice + // changes that were not yet persisted to Blockchain's dao. + baseStorageFee = bc.contracts.Policy.GetStoragePriceInternal(d) + } + ic := interop.NewContext(trigger, bc, d, baseExecFee, baseStorageFee, bc.contracts.Management.GetContract, bc.contracts.Contracts, block, tx, bc.log) ic.Functions = systemInterops switch { case tx != nil: diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index f4792645a..22c1486e8 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -41,48 +41,49 @@ type Ledger interface { GetBlock(hash util.Uint256) (*block.Block, error) GetConfig() config.ProtocolConfiguration GetHeaderHash(int) util.Uint256 - GetStoragePrice() int64 } // Context represents context in which interops are executed. type Context struct { - Chain Ledger - Container hash.Hashable - Network uint32 - Natives []Contract - Trigger trigger.Type - Block *block.Block - NonceData [16]byte - Tx *transaction.Transaction - DAO *dao.Simple - Notifications []state.NotificationEvent - Log *zap.Logger - VM *vm.VM - Functions []Function - Invocations map[util.Uint160]int - cancelFuncs []context.CancelFunc - getContract func(*dao.Simple, util.Uint160) (*state.Contract, error) - baseExecFee int64 - signers []transaction.Signer + Chain Ledger + Container hash.Hashable + Network uint32 + Natives []Contract + Trigger trigger.Type + Block *block.Block + NonceData [16]byte + Tx *transaction.Transaction + DAO *dao.Simple + Notifications []state.NotificationEvent + Log *zap.Logger + VM *vm.VM + Functions []Function + Invocations map[util.Uint160]int + cancelFuncs []context.CancelFunc + getContract func(*dao.Simple, util.Uint160) (*state.Contract, error) + baseExecFee int64 + baseStorageFee int64 + signers []transaction.Signer } // NewContext returns new interop context. -func NewContext(trigger trigger.Type, bc Ledger, d *dao.Simple, baseExecFee int64, +func NewContext(trigger trigger.Type, bc Ledger, d *dao.Simple, baseExecFee, baseStorageFee int64, getContract func(*dao.Simple, util.Uint160) (*state.Contract, error), natives []Contract, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context { dao := d.GetPrivate() return &Context{ - Chain: bc, - Network: uint32(bc.GetConfig().Magic), - Natives: natives, - Trigger: trigger, - Block: block, - Tx: tx, - DAO: dao, - Log: log, - Invocations: make(map[util.Uint160]int), - getContract: getContract, - baseExecFee: baseExecFee, + Chain: bc, + Network: uint32(bc.GetConfig().Magic), + Natives: natives, + Trigger: trigger, + Block: block, + Tx: tx, + DAO: dao, + Log: log, + Invocations: make(map[util.Uint160]int), + getContract: getContract, + baseExecFee: baseExecFee, + baseStorageFee: baseStorageFee, } } @@ -288,6 +289,11 @@ func (ic *Context) BaseExecFee() int64 { return ic.baseExecFee } +// BaseStorageFee represents price for storing one byte of data in the contract storage. +func (ic *Context) BaseStorageFee() int64 { + return ic.baseStorageFee +} + // SyscallHandler handles syscall with id. func (ic *Context) SyscallHandler(_ *vm.VM, id uint32) error { f := ic.GetFunction(id) diff --git a/pkg/core/interop/crypto/ecdsa_test.go b/pkg/core/interop/crypto/ecdsa_test.go index 5f6839674..9cfb370e1 100644 --- a/pkg/core/interop/crypto/ecdsa_test.go +++ b/pkg/core/interop/crypto/ecdsa_test.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/fee" "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/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -72,7 +73,7 @@ func initCheckMultisigVMNoArgs(container *transaction.Transaction) *vm.VM { trigger.Verification, fakechain.NewFakeChain(), dao.NewSimple(storage.NewMemoryStore(), false, false), - interop.DefaultBaseExecFee, nil, nil, nil, + interop.DefaultBaseExecFee, native.DefaultStoragePrice, nil, nil, nil, container, nil) ic.Container = container diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 3a6facde2..42312f1f3 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -126,7 +126,7 @@ func putWithContext(ic *interop.Context, stc *StorageContext, key []byte, value sizeInc = (len(si)-1)/4 + 1 + len(value) - len(si) } } - if !ic.VM.AddGas(int64(sizeInc) * ic.Chain.GetStoragePrice()) { + if !ic.VM.AddGas(int64(sizeInc) * ic.BaseStorageFee()) { return errGasLimitExceeded } ic.DAO.PutStorageItem(stc.ID, key, value) diff --git a/pkg/core/native/interop.go b/pkg/core/native/interop.go index c97850138..92fdf3717 100644 --- a/pkg/core/native/interop.go +++ b/pkg/core/native/interop.go @@ -43,7 +43,7 @@ func Call(ic *interop.Context) error { version, m.MD.Name, ic.VM.Context().GetCallFlags(), m.RequiredFlags) } invokeFee := m.CPUFee*ic.Chain.GetBaseExecFee() + - m.StorageFee*ic.Chain.GetStoragePrice() + m.StorageFee*ic.BaseStorageFee() if !ic.VM.AddGas(invokeFee) { return errors.New("gas limit exceeded") } diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index 4591133c3..dc9257331 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -198,7 +198,7 @@ func (m *Management) getNefAndManifestFromItems(ic *interop.Context, args []stac return nil, nil, fmt.Errorf("invalid manifest: %w", err) } - gas := ic.Chain.GetStoragePrice() * int64(len(nefBytes)+len(manifestBytes)) + gas := ic.BaseStorageFee() * int64(len(nefBytes)+len(manifestBytes)) if isDeploy { fee := m.minimumDeploymentFee(ic.DAO) if fee > gas {