mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-02 09:45:50 +00:00
core: use proper storage price within the whole interop context
We shouldn't use StoragePrice from Blockchain because its dao doesn't contain the whole set of changes from previouse transactions in the current block. Instead, we should use an updated storage price for each transaction and retrieve the price from cached DAO.
This commit is contained in:
parent
91a4bc5beb
commit
544f2c2cb2
7 changed files with 51 additions and 38 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core"
|
"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/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
"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/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
|
@ -200,7 +201,7 @@ func TestAppCall(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fc := fakechain.NewFakeChain()
|
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) {
|
t.Run("valid script", func(t *testing.T) {
|
||||||
src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE()))
|
src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE()))
|
||||||
|
|
|
@ -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 {
|
func (bc *Blockchain) newInteropContext(trigger trigger.Type, d *dao.Simple, block *block.Block, tx *transaction.Transaction) *interop.Context {
|
||||||
baseExecFee := int64(interop.DefaultBaseExecFee)
|
baseExecFee := int64(interop.DefaultBaseExecFee)
|
||||||
|
|
||||||
if block == nil || block.Index != 0 {
|
if block == nil || block.Index != 0 {
|
||||||
// Use provided dao instead of Blockchain's one to fetch possible ExecFeeFactor
|
// Use provided dao instead of Blockchain's one to fetch possible ExecFeeFactor
|
||||||
// changes that were not yet persisted to Blockchain's dao.
|
// changes that were not yet persisted to Blockchain's dao.
|
||||||
baseExecFee = bc.contracts.Policy.GetExecFeeFactorInternal(d)
|
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
|
ic.Functions = systemInterops
|
||||||
switch {
|
switch {
|
||||||
case tx != nil:
|
case tx != nil:
|
||||||
|
|
|
@ -41,7 +41,6 @@ type Ledger interface {
|
||||||
GetBlock(hash util.Uint256) (*block.Block, error)
|
GetBlock(hash util.Uint256) (*block.Block, error)
|
||||||
GetConfig() config.ProtocolConfiguration
|
GetConfig() config.ProtocolConfiguration
|
||||||
GetHeaderHash(int) util.Uint256
|
GetHeaderHash(int) util.Uint256
|
||||||
GetStoragePrice() int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Context represents context in which interops are executed.
|
// Context represents context in which interops are executed.
|
||||||
|
@ -63,11 +62,12 @@ type Context struct {
|
||||||
cancelFuncs []context.CancelFunc
|
cancelFuncs []context.CancelFunc
|
||||||
getContract func(*dao.Simple, util.Uint160) (*state.Contract, error)
|
getContract func(*dao.Simple, util.Uint160) (*state.Contract, error)
|
||||||
baseExecFee int64
|
baseExecFee int64
|
||||||
|
baseStorageFee int64
|
||||||
signers []transaction.Signer
|
signers []transaction.Signer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext returns new interop context.
|
// 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,
|
getContract func(*dao.Simple, util.Uint160) (*state.Contract, error), natives []Contract,
|
||||||
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
|
block *block.Block, tx *transaction.Transaction, log *zap.Logger) *Context {
|
||||||
dao := d.GetPrivate()
|
dao := d.GetPrivate()
|
||||||
|
@ -83,6 +83,7 @@ func NewContext(trigger trigger.Type, bc Ledger, d *dao.Simple, baseExecFee int6
|
||||||
Invocations: make(map[util.Uint160]int),
|
Invocations: make(map[util.Uint160]int),
|
||||||
getContract: getContract,
|
getContract: getContract,
|
||||||
baseExecFee: baseExecFee,
|
baseExecFee: baseExecFee,
|
||||||
|
baseStorageFee: baseStorageFee,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,6 +289,11 @@ func (ic *Context) BaseExecFee() int64 {
|
||||||
return ic.baseExecFee
|
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.
|
// SyscallHandler handles syscall with id.
|
||||||
func (ic *Context) SyscallHandler(_ *vm.VM, id uint32) error {
|
func (ic *Context) SyscallHandler(_ *vm.VM, id uint32) error {
|
||||||
f := ic.GetFunction(id)
|
f := ic.GetFunction(id)
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
"github.com/nspcc-dev/neo-go/pkg/core/dao"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/fee"
|
"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/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/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"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/hash"
|
||||||
|
@ -72,7 +73,7 @@ func initCheckMultisigVMNoArgs(container *transaction.Transaction) *vm.VM {
|
||||||
trigger.Verification,
|
trigger.Verification,
|
||||||
fakechain.NewFakeChain(),
|
fakechain.NewFakeChain(),
|
||||||
dao.NewSimple(storage.NewMemoryStore(), false, false),
|
dao.NewSimple(storage.NewMemoryStore(), false, false),
|
||||||
interop.DefaultBaseExecFee, nil, nil, nil,
|
interop.DefaultBaseExecFee, native.DefaultStoragePrice, nil, nil, nil,
|
||||||
container,
|
container,
|
||||||
nil)
|
nil)
|
||||||
ic.Container = container
|
ic.Container = container
|
||||||
|
|
|
@ -126,7 +126,7 @@ func putWithContext(ic *interop.Context, stc *StorageContext, key []byte, value
|
||||||
sizeInc = (len(si)-1)/4 + 1 + len(value) - len(si)
|
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
|
return errGasLimitExceeded
|
||||||
}
|
}
|
||||||
ic.DAO.PutStorageItem(stc.ID, key, value)
|
ic.DAO.PutStorageItem(stc.ID, key, value)
|
||||||
|
|
|
@ -43,7 +43,7 @@ func Call(ic *interop.Context) error {
|
||||||
version, m.MD.Name, ic.VM.Context().GetCallFlags(), m.RequiredFlags)
|
version, m.MD.Name, ic.VM.Context().GetCallFlags(), m.RequiredFlags)
|
||||||
}
|
}
|
||||||
invokeFee := m.CPUFee*ic.Chain.GetBaseExecFee() +
|
invokeFee := m.CPUFee*ic.Chain.GetBaseExecFee() +
|
||||||
m.StorageFee*ic.Chain.GetStoragePrice()
|
m.StorageFee*ic.BaseStorageFee()
|
||||||
if !ic.VM.AddGas(invokeFee) {
|
if !ic.VM.AddGas(invokeFee) {
|
||||||
return errors.New("gas limit exceeded")
|
return errors.New("gas limit exceeded")
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,7 @@ func (m *Management) getNefAndManifestFromItems(ic *interop.Context, args []stac
|
||||||
return nil, nil, fmt.Errorf("invalid manifest: %w", err)
|
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 {
|
if isDeploy {
|
||||||
fee := m.minimumDeploymentFee(ic.DAO)
|
fee := m.minimumDeploymentFee(ic.DAO)
|
||||||
if fee > gas {
|
if fee > gas {
|
||||||
|
|
Loading…
Reference in a new issue