mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 23:33:37 +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,48 +41,49 @@ 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.
|
||||||
type Context struct {
|
type Context struct {
|
||||||
Chain Ledger
|
Chain Ledger
|
||||||
Container hash.Hashable
|
Container hash.Hashable
|
||||||
Network uint32
|
Network uint32
|
||||||
Natives []Contract
|
Natives []Contract
|
||||||
Trigger trigger.Type
|
Trigger trigger.Type
|
||||||
Block *block.Block
|
Block *block.Block
|
||||||
NonceData [16]byte
|
NonceData [16]byte
|
||||||
Tx *transaction.Transaction
|
Tx *transaction.Transaction
|
||||||
DAO *dao.Simple
|
DAO *dao.Simple
|
||||||
Notifications []state.NotificationEvent
|
Notifications []state.NotificationEvent
|
||||||
Log *zap.Logger
|
Log *zap.Logger
|
||||||
VM *vm.VM
|
VM *vm.VM
|
||||||
Functions []Function
|
Functions []Function
|
||||||
Invocations map[util.Uint160]int
|
Invocations map[util.Uint160]int
|
||||||
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
|
||||||
signers []transaction.Signer
|
baseStorageFee int64
|
||||||
|
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()
|
||||||
return &Context{
|
return &Context{
|
||||||
Chain: bc,
|
Chain: bc,
|
||||||
Network: uint32(bc.GetConfig().Magic),
|
Network: uint32(bc.GetConfig().Magic),
|
||||||
Natives: natives,
|
Natives: natives,
|
||||||
Trigger: trigger,
|
Trigger: trigger,
|
||||||
Block: block,
|
Block: block,
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
DAO: dao,
|
DAO: dao,
|
||||||
Log: log,
|
Log: log,
|
||||||
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