From 260bcd373cad41c00745c32e1f54463b7cf07b29 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 2 Feb 2021 18:46:43 +0300 Subject: [PATCH 1/5] core: store initial native values into DAO --- internal/fakechain/fakechain.go | 2 +- pkg/core/blockchain.go | 6 +++ pkg/core/interop_system_test.go | 10 ++--- pkg/core/native/management.go | 24 ++++++------ pkg/core/native/management_test.go | 4 +- pkg/core/native/name_service.go | 7 ++-- pkg/core/native/nonfungible.go | 9 +++-- pkg/core/native/notary.go | 11 ++++-- pkg/core/native/oracle.go | 10 +++-- pkg/core/native/policy.go | 60 ++++++++++++++++++++---------- pkg/core/native/util.go | 20 ++++++++++ pkg/core/native_oracle_test.go | 16 ++++---- pkg/core/native_policy_test.go | 4 +- pkg/core/oracle_test.go | 52 +++++++++++++------------- 14 files changed, 147 insertions(+), 88 deletions(-) diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index 3b79ebc8b..97d690a6c 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -118,7 +118,7 @@ func (chain *FakeChain) GetBaseExecFee() int64 { // GetStoragePrice implements Policer interface. func (chain *FakeChain) GetStoragePrice() int64 { - return native.StoragePrice + return native.DefaultStoragePrice } // GetMaxVerificationGAS implements Policer interface. diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 20481bd02..93000f95f 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1918,6 +1918,9 @@ func (bc *Blockchain) GetPolicer() blockchainer.Policer { // GetBaseExecFee return execution price for `NOP`. func (bc *Blockchain) GetBaseExecFee() int64 { + if bc.BlockHeight() == 0 { + return interop.DefaultBaseExecFee + } return bc.contracts.Policy.GetExecFeeFactorInternal(bc.dao) } @@ -1938,6 +1941,9 @@ func (bc *Blockchain) GetMaxVerificationGAS() int64 { // GetStoragePrice returns current storage price. func (bc *Blockchain) GetStoragePrice() int64 { + if bc.BlockHeight() == 0 { + return native.DefaultStoragePrice + } return bc.contracts.Policy.GetStoragePriceInternal(bc.dao) } diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 9b574242e..39fe5af80 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -355,23 +355,23 @@ func TestStoragePut(t *testing.T) { } t.Run("create, not enough gas", func(t *testing.T) { - initVM(t, []byte{1}, []byte{2, 3}, 2*native.StoragePrice) + initVM(t, []byte{1}, []byte{2, 3}, 2*native.DefaultStoragePrice) err := storagePut(ic) require.True(t, errors.Is(err, errGasLimitExceeded), "got: %v", err) }) - initVM(t, []byte{4}, []byte{5, 6}, 3*native.StoragePrice) + initVM(t, []byte{4}, []byte{5, 6}, 3*native.DefaultStoragePrice) require.NoError(t, storagePut(ic)) t.Run("update", func(t *testing.T) { t.Run("not enough gas", func(t *testing.T) { - initVM(t, []byte{4}, []byte{5, 6, 7, 8}, native.StoragePrice) + initVM(t, []byte{4}, []byte{5, 6, 7, 8}, native.DefaultStoragePrice) err := storagePut(ic) require.True(t, errors.Is(err, errGasLimitExceeded), "got: %v", err) }) - initVM(t, []byte{4}, []byte{5, 6, 7, 8}, 3*native.StoragePrice) + initVM(t, []byte{4}, []byte{5, 6, 7, 8}, 3*native.DefaultStoragePrice) require.NoError(t, storagePut(ic)) - initVM(t, []byte{4}, []byte{5, 6}, native.StoragePrice) + initVM(t, []byte{4}, []byte{5, 6}, native.DefaultStoragePrice) require.NoError(t, storagePut(ic)) }) diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index 083829570..217168afc 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -33,9 +33,6 @@ type Management struct { contracts map[util.Uint160]*state.Contract } -// StoragePrice is the price to pay for 1 byte of storage. -const StoragePrice = 100000 - const ( managementContractID = -1 @@ -386,7 +383,7 @@ func (m *Management) getMinimumDeploymentFee(ic *interop.Context, args []stackit // GetMinimumDeploymentFee returns the minimum required fee for contract deploy. func (m *Management) GetMinimumDeploymentFee(dao dao.DAO) int64 { - return int64(getUint32WithKey(m.ContractID, dao, keyMinimumDeploymentFee, defaultMinimumDeploymentFee)) + return getIntWithKey(m.ContractID, dao, keyMinimumDeploymentFee) } func (m *Management) setMinimumDeploymentFee(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -397,7 +394,7 @@ func (m *Management) setMinimumDeploymentFee(ic *interop.Context, args []stackit if !m.NEO.checkCommittee(ic) { panic("invalid committee signature") } - err := setUint32WithKey(m.ContractID, ic.DAO, keyMinimumDeploymentFee, value) + err := setIntWithKey(m.ContractID, ic.DAO, keyMinimumDeploymentFee, int64(value)) if err != nil { panic(err) } @@ -508,7 +505,10 @@ func (m *Management) PostPersist(ic *interop.Context) error { // Initialize implements Contract interface. func (m *Management) Initialize(ic *interop.Context) error { - return setUint32WithKey(m.ContractID, ic.DAO, keyMinimumDeploymentFee, defaultMinimumDeploymentFee) + if err := setIntWithKey(m.ContractID, ic.DAO, keyMinimumDeploymentFee, defaultMinimumDeploymentFee); err != nil { + return err + } + return setIntWithKey(m.ContractID, ic.DAO, keyNextAvailableID, 1) } // PutContractState saves given contract state into given DAO. @@ -525,16 +525,14 @@ func (m *Management) PutContractState(d dao.DAO, cs *state.Contract) error { } func (m *Management) getNextContractID(d dao.DAO) (int32, error) { - var id = big.NewInt(1) si := d.GetStorageItem(m.ContractID, keyNextAvailableID) - if si != nil { - id = bigint.FromBytes(si.Value) - } else { - si = new(state.StorageItem) - si.Value = make([]byte, 0, 2) + if si == nil { + return 0, errors.New("nextAvailableID is not initialized") + } + id := bigint.FromBytes(si.Value) ret := int32(id.Int64()) - id.Add(id, big.NewInt(1)) + id.Add(id, intOne) si.Value = bigint.ToPreallocatedBytes(id, si.Value) return ret, d.PutStorageItem(m.ContractID, keyNextAvailableID, si) } diff --git a/pkg/core/native/management_test.go b/pkg/core/native/management_test.go index fa654e985..dd66e86d7 100644 --- a/pkg/core/native/management_test.go +++ b/pkg/core/native/management_test.go @@ -5,6 +5,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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/state" "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" @@ -15,7 +16,8 @@ import ( func TestDeployGetUpdateDestroyContract(t *testing.T) { mgmt := newManagement() - d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) + d := dao.NewCached(dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)) + mgmt.Initialize(&interop.Context{DAO: d}) script := []byte{1} sender := util.Uint160{1, 2, 3} ne, err := nef.NewFile(script) diff --git a/pkg/core/native/name_service.go b/pkg/core/native/name_service.go index 0690cb414..4727ec216 100644 --- a/pkg/core/native/name_service.go +++ b/pkg/core/native/name_service.go @@ -172,11 +172,12 @@ func (n *NameService) Metadata() *interop.ContractMD { // Initialize implements interop.Contract interface. func (n *NameService) Initialize(ic *interop.Context) error { - si := &state.StorageItem{Value: bigint.ToBytes(big.NewInt(DefaultDomainPrice))} - if err := ic.DAO.PutStorageItem(n.ContractID, []byte{prefixDomainPrice}, si); err != nil { + if err := n.nonfungible.Initialize(ic); err != nil { + return err + } + if err := setIntWithKey(n.ContractID, ic.DAO, []byte{prefixDomainPrice}, DefaultDomainPrice); err != nil { return err } - roots := stringList{} return putSerializableToDAO(n.ContractID, ic.DAO, []byte{prefixRoots}, &roots) } diff --git a/pkg/core/native/nonfungible.go b/pkg/core/native/nonfungible.go index 36826506f..ba0d3e4b2 100644 --- a/pkg/core/native/nonfungible.go +++ b/pkg/core/native/nonfungible.go @@ -50,8 +50,6 @@ const ( var ( nftTotalSupplyKey = []byte{prefixNFTTotalSupply} - - intOne = big.NewInt(1) ) func newNonFungible(name string, id int32, symbol string, decimals byte) *nonfungible { @@ -120,6 +118,11 @@ func newNonFungible(name string, id int32, symbol string, decimals byte) *nonfun return n } +// Initialize implements interop.Contract interface. +func (n nonfungible) Initialize(ic *interop.Context) error { + return setIntWithKey(n.ContractID, ic.DAO, nftTotalSupplyKey, 0) +} + func (n *nonfungible) symbol(_ *interop.Context, _ []stackitem.Item) stackitem.Item { return stackitem.NewByteArray([]byte(n.tokenSymbol)) } @@ -135,7 +138,7 @@ func (n *nonfungible) totalSupply(ic *interop.Context, _ []stackitem.Item) stack func (n *nonfungible) TotalSupply(d dao.DAO) *big.Int { si := d.GetStorageItem(n.ContractID, nftTotalSupplyKey) if si == nil { - return big.NewInt(0) + panic(errors.New("total supply is not initialized")) } return bigint.FromBytes(si.Value) } diff --git a/pkg/core/native/notary.go b/pkg/core/native/notary.go index 0a27a5dec..9713ba4ca 100644 --- a/pkg/core/native/notary.go +++ b/pkg/core/native/notary.go @@ -108,6 +108,11 @@ func (n *Notary) Metadata() *interop.ContractMD { // Initialize initializes Notary native contract and implements Contract interface. func (n *Notary) Initialize(ic *interop.Context) error { + err := setIntWithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta) + if err != nil { + return err + } + n.isValid = true n.maxNotValidBeforeDelta = defaultMaxNotValidBeforeDelta return nil @@ -166,7 +171,7 @@ func (n *Notary) PostPersist(ic *interop.Context) error { return nil } - n.maxNotValidBeforeDelta = getUint32WithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta) + n.maxNotValidBeforeDelta = uint32(getIntWithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey)) n.isValid = true return nil } @@ -379,7 +384,7 @@ func (n *Notary) GetMaxNotValidBeforeDelta(dao dao.DAO) uint32 { if n.isValid { return n.maxNotValidBeforeDelta } - return getUint32WithKey(n.ContractID, dao, maxNotValidBeforeDeltaKey, defaultMaxNotValidBeforeDelta) + return uint32(getIntWithKey(n.ContractID, dao, maxNotValidBeforeDeltaKey)) } // setMaxNotValidBeforeDelta is Notary contract method and sets the maximum NotValidBefore delta. @@ -393,7 +398,7 @@ func (n *Notary) setMaxNotValidBeforeDelta(ic *interop.Context, args []stackitem } n.lock.Lock() defer n.lock.Unlock() - err := setUint32WithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey, value) + err := setIntWithKey(n.ContractID, ic.DAO, maxNotValidBeforeDeltaKey, int64(value)) if err != nil { panic(fmt.Errorf("failed to put value into the storage: %w", err)) } diff --git a/pkg/core/native/oracle.go b/pkg/core/native/oracle.go index ed775d7d4..2ef566f68 100644 --- a/pkg/core/native/oracle.go +++ b/pkg/core/native/oracle.go @@ -20,6 +20,7 @@ import ( "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/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" @@ -201,8 +202,7 @@ func (o *Oracle) Metadata() *interop.ContractMD { // Initialize initializes Oracle contract. func (o *Oracle) Initialize(ic *interop.Context) error { - si := &state.StorageItem{Value: make([]byte, 8)} // uint64(0) LE - return ic.DAO.PutStorageItem(o.ContractID, prefixRequestID, si) + return setIntWithKey(o.ContractID, ic.DAO, prefixRequestID, 0) } func getResponse(tx *transaction.Transaction) *transaction.OracleResponse { @@ -302,8 +302,10 @@ func (o *Oracle) RequestInternal(ic *interop.Context, url string, filter *string callingHash := ic.VM.GetCallingScriptHash() o.GAS.mint(ic, o.Hash, gas, false) si := ic.DAO.GetStorageItem(o.ContractID, prefixRequestID) - id := binary.LittleEndian.Uint64(si.Value) + 1 - binary.LittleEndian.PutUint64(si.Value, id) + itemID := bigint.FromBytes(si.Value) + id := itemID.Uint64() + itemID.Add(itemID, intOne) + si.Value = bigint.ToPreallocatedBytes(itemID, si.Value) if err := ic.DAO.PutStorageItem(o.ContractID, prefixRequestID, si); err != nil { return err } diff --git a/pkg/core/native/policy.go b/pkg/core/native/policy.go index 4afdef5ce..79a9edf40 100644 --- a/pkg/core/native/policy.go +++ b/pkg/core/native/policy.go @@ -29,6 +29,9 @@ const ( defaultFeePerByte = 1000 defaultMaxVerificationGas = 50000000 defaultMaxBlockSystemFee = 9000 * GASFactor + // DefaultStoragePrice is the price to pay for 1 byte of storage. + DefaultStoragePrice = 100000 + // minBlockSystemFee is the minimum allowed system fee per block. minBlockSystemFee = 4007600 // maxExecFeeFactor is the maximum allowed execution fee factor. @@ -163,6 +166,25 @@ func (p *Policy) Metadata() *interop.ContractMD { // Initialize initializes Policy native contract and implements Contract interface. func (p *Policy) Initialize(ic *interop.Context) error { + if err := setIntWithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey, defaultMaxTransactionsPerBlock); err != nil { + return err + } + if err := setIntWithKey(p.ContractID, ic.DAO, feePerByteKey, defaultFeePerByte); err != nil { + return err + } + if err := setIntWithKey(p.ContractID, ic.DAO, maxBlockSizeKey, defaultMaxBlockSize); err != nil { + return err + } + if err := setIntWithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey, defaultMaxBlockSystemFee); err != nil { + return err + } + if err := setIntWithKey(p.ContractID, ic.DAO, execFeeFactorKey, defaultExecFeeFactor); err != nil { + return err + } + if err := setIntWithKey(p.ContractID, ic.DAO, storagePriceKey, DefaultStoragePrice); err != nil { + return err + } + p.isValid = true p.maxTransactionsPerBlock = defaultMaxTransactionsPerBlock p.maxBlockSize = defaultMaxBlockSize @@ -170,7 +192,7 @@ func (p *Policy) Initialize(ic *interop.Context) error { p.feePerByte = defaultFeePerByte p.maxBlockSystemFee = defaultMaxBlockSystemFee p.maxVerificationGas = defaultMaxVerificationGas - p.storagePrice = StoragePrice + p.storagePrice = DefaultStoragePrice p.blockedAccounts = make([]util.Uint160, 0) return nil @@ -189,13 +211,13 @@ func (p *Policy) PostPersist(ic *interop.Context) error { return nil } - p.maxTransactionsPerBlock = getUint32WithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey, defaultMaxTransactionsPerBlock) - p.maxBlockSize = getUint32WithKey(p.ContractID, ic.DAO, maxBlockSizeKey, defaultMaxBlockSize) - p.execFeeFactor = getUint32WithKey(p.ContractID, ic.DAO, execFeeFactorKey, defaultExecFeeFactor) - p.feePerByte = getInt64WithKey(p.ContractID, ic.DAO, feePerByteKey, defaultFeePerByte) - p.maxBlockSystemFee = getInt64WithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey, defaultMaxBlockSystemFee) + p.maxTransactionsPerBlock = uint32(getIntWithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey)) + p.maxBlockSize = uint32(getIntWithKey(p.ContractID, ic.DAO, maxBlockSizeKey)) + p.execFeeFactor = uint32(getIntWithKey(p.ContractID, ic.DAO, execFeeFactorKey)) + p.feePerByte = getIntWithKey(p.ContractID, ic.DAO, feePerByteKey) + p.maxBlockSystemFee = getIntWithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey) p.maxVerificationGas = defaultMaxVerificationGas - p.storagePrice = getUint32WithKey(p.ContractID, ic.DAO, storagePriceKey, StoragePrice) + p.storagePrice = uint32(getIntWithKey(p.ContractID, ic.DAO, storagePriceKey)) p.blockedAccounts = make([]util.Uint160, 0) siMap, err := ic.DAO.GetStorageItemsWithPrefix(p.ContractID, []byte{blockedAccountPrefix}) @@ -231,7 +253,7 @@ func (p *Policy) GetMaxTransactionsPerBlockInternal(dao dao.DAO) uint32 { if p.isValid { return p.maxTransactionsPerBlock } - return getUint32WithKey(p.ContractID, dao, maxTransactionsPerBlockKey, defaultMaxTransactionsPerBlock) + return uint32(getIntWithKey(p.ContractID, dao, maxTransactionsPerBlockKey)) } // getMaxBlockSize is Policy contract method and returns maximum block size. @@ -246,7 +268,7 @@ func (p *Policy) GetMaxBlockSizeInternal(dao dao.DAO) uint32 { if p.isValid { return p.maxBlockSize } - return getUint32WithKey(p.ContractID, dao, maxBlockSizeKey, defaultMaxBlockSize) + return uint32(getIntWithKey(p.ContractID, dao, maxBlockSizeKey)) } // getFeePerByte is Policy contract method and returns required transaction's fee @@ -262,7 +284,7 @@ func (p *Policy) GetFeePerByteInternal(dao dao.DAO) int64 { if p.isValid { return p.feePerByte } - return getInt64WithKey(p.ContractID, dao, feePerByteKey, defaultFeePerByte) + return getIntWithKey(p.ContractID, dao, feePerByteKey) } // GetMaxVerificationGas returns maximum gas allowed to be burned during verificaion. @@ -286,7 +308,7 @@ func (p *Policy) GetMaxBlockSystemFeeInternal(dao dao.DAO) int64 { if p.isValid { return p.maxBlockSystemFee } - return getInt64WithKey(p.ContractID, dao, maxBlockSystemFeeKey, defaultMaxBlockSystemFee) + return getIntWithKey(p.ContractID, dao, maxBlockSystemFeeKey) } func (p *Policy) getExecFeeFactor(ic *interop.Context, _ []stackitem.Item) stackitem.Item { @@ -300,7 +322,7 @@ func (p *Policy) GetExecFeeFactorInternal(d dao.DAO) int64 { if p.isValid { return int64(p.execFeeFactor) } - return int64(getUint32WithKey(p.ContractID, d, execFeeFactorKey, defaultExecFeeFactor)) + return getIntWithKey(p.ContractID, d, execFeeFactorKey) } func (p *Policy) setExecFeeFactor(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -313,7 +335,7 @@ func (p *Policy) setExecFeeFactor(ic *interop.Context, args []stackitem.Item) st } p.lock.Lock() defer p.lock.Unlock() - err := setUint32WithKey(p.ContractID, ic.DAO, execFeeFactorKey, uint32(value)) + err := setIntWithKey(p.ContractID, ic.DAO, execFeeFactorKey, int64(value)) if err != nil { panic(err) } @@ -356,7 +378,7 @@ func (p *Policy) GetStoragePriceInternal(d dao.DAO) int64 { if p.isValid { return int64(p.storagePrice) } - return int64(getUint32WithKey(p.ContractID, d, storagePriceKey, StoragePrice)) + return getIntWithKey(p.ContractID, d, storagePriceKey) } func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -369,7 +391,7 @@ func (p *Policy) setStoragePrice(ic *interop.Context, args []stackitem.Item) sta } p.lock.Lock() defer p.lock.Unlock() - err := setUint32WithKey(p.ContractID, ic.DAO, storagePriceKey, uint32(value)) + err := setIntWithKey(p.ContractID, ic.DAO, storagePriceKey, int64(value)) if err != nil { panic(err) } @@ -389,7 +411,7 @@ func (p *Policy) setMaxTransactionsPerBlock(ic *interop.Context, args []stackite } p.lock.Lock() defer p.lock.Unlock() - err := setUint32WithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey, value) + err := setIntWithKey(p.ContractID, ic.DAO, maxTransactionsPerBlockKey, int64(value)) if err != nil { panic(err) } @@ -408,7 +430,7 @@ func (p *Policy) setMaxBlockSize(ic *interop.Context, args []stackitem.Item) sta } p.lock.Lock() defer p.lock.Unlock() - err := setUint32WithKey(p.ContractID, ic.DAO, maxBlockSizeKey, value) + err := setIntWithKey(p.ContractID, ic.DAO, maxBlockSizeKey, int64(value)) if err != nil { panic(err) } @@ -427,7 +449,7 @@ func (p *Policy) setFeePerByte(ic *interop.Context, args []stackitem.Item) stack } p.lock.Lock() defer p.lock.Unlock() - err := setInt64WithKey(p.ContractID, ic.DAO, feePerByteKey, value) + err := setIntWithKey(p.ContractID, ic.DAO, feePerByteKey, value) if err != nil { panic(err) } @@ -446,7 +468,7 @@ func (p *Policy) setMaxBlockSystemFee(ic *interop.Context, args []stackitem.Item } p.lock.Lock() defer p.lock.Unlock() - err := setInt64WithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey, value) + err := setIntWithKey(p.ContractID, ic.DAO, maxBlockSystemFeeKey, value) if err != nil { panic(err) } diff --git a/pkg/core/native/util.go b/pkg/core/native/util.go index 929b3d1e3..30d5e9e8a 100644 --- a/pkg/core/native/util.go +++ b/pkg/core/native/util.go @@ -2,15 +2,21 @@ package native import ( "encoding/binary" + "encoding/hex" + "fmt" + "math/big" "github.com/nspcc-dev/neo-go/pkg/core/dao" "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/encoding/bigint" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) +var intOne = big.NewInt(1) + func getSerializableFromDAO(id int32, d dao.DAO, key []byte, item io.Serializable) error { si := d.GetStorageItem(id, key) if si == nil { @@ -64,6 +70,20 @@ func setUint32WithKey(id int32, dao dao.DAO, key []byte, value uint32) error { return dao.PutStorageItem(id, key, si) } +func setIntWithKey(id int32, dao dao.DAO, key []byte, value int64) error { + si := &state.StorageItem{Value: bigint.ToBytes(big.NewInt(value))} + return dao.PutStorageItem(id, key, si) +} + +func getIntWithKey(id int32, dao dao.DAO, key []byte) int64 { + si := dao.GetStorageItem(id, key) + if si == nil { + panic(fmt.Errorf("item with id = %d and key = %s is not initialized", id, hex.EncodeToString(key))) + + } + return bigint.FromBytes(si.Value).Int64() +} + // makeUint160Key creates a key from account script hash. func makeUint160Key(prefix byte, h util.Uint160) []byte { k := make([]byte, util.Uint160Size+1) diff --git a/pkg/core/native_oracle_test.go b/pkg/core/native_oracle_test.go index b6ac58d64..a99aa2c76 100644 --- a/pkg/core/native_oracle_test.go +++ b/pkg/core/native_oracle_test.go @@ -124,7 +124,7 @@ func TestOracle_Request(t *testing.T) { userData := []byte("custom info") txHash := putOracleRequest(t, cs.Hash, bc, "url", &filter, "handle", userData, gasForResponse) - req, err := orc.GetRequestInternal(bc.dao, 1) + req, err := orc.GetRequestInternal(bc.dao, 0) require.NotNil(t, req) require.NoError(t, err) require.Equal(t, txHash, req.OriginalTxID) @@ -136,7 +136,7 @@ func TestOracle_Request(t *testing.T) { idList, err := orc.GetIDListInternal(bc.dao, "url") require.NoError(t, err) - require.Equal(t, &native.IDList{1}, idList) + require.Equal(t, &native.IDList{0}, idList) // Finish. priv, err := keys.NewPrivateKey() @@ -161,7 +161,7 @@ func TestOracle_Request(t *testing.T) { require.True(t, errors.Is(err, native.ErrResponseNotFound), "got: %v", err) resp := &transaction.OracleResponse{ - ID: 13, + ID: 12, Code: transaction.Success, Result: []byte{4, 8, 15, 16, 23, 42}, } @@ -173,7 +173,7 @@ func TestOracle_Request(t *testing.T) { require.True(t, errors.Is(err, native.ErrRequestNotFound), "got: %v", err) // We need to ensure that callback is called thus, executing full script is necessary. - resp.ID = 1 + resp.ID = 0 ic.VM.LoadScriptWithFlags(tx.Script, callflag.All) require.NoError(t, ic.VM.Run()) @@ -189,18 +189,18 @@ func TestOracle_Request(t *testing.T) { require.Equal(t, resp.Result, arr[3].Value()) // Check that processed request is removed during `postPersist`. - _, err = orc.GetRequestInternal(ic.DAO, 1) + _, err = orc.GetRequestInternal(ic.DAO, 0) require.NoError(t, err) require.NoError(t, orc.PostPersist(ic)) - _, err = orc.GetRequestInternal(ic.DAO, 1) + _, err = orc.GetRequestInternal(ic.DAO, 0) require.Error(t, err) t.Run("ErrorOnFinish", func(t *testing.T) { - const reqID = 2 + const reqID = 1 putOracleRequest(t, cs.Hash, bc, "url", nil, "handle", []byte{1, 2}, gasForResponse) - _, err := orc.GetRequestInternal(bc.dao, reqID) // ensure ID is 2 + _, err := orc.GetRequestInternal(bc.dao, reqID) // ensure ID is 1 require.NoError(t, err) tx = transaction.New(netmode.UnitTestNet, orc.GetOracleResponseScript(), 0) diff --git a/pkg/core/native_policy_test.go b/pkg/core/native_policy_test.go index 6745db604..3ef5c4828 100644 --- a/pkg/core/native_policy_test.go +++ b/pkg/core/native_policy_test.go @@ -142,10 +142,10 @@ func TestStoragePrice(t *testing.T) { t.Run("get, internal method", func(t *testing.T) { n := chain.contracts.Policy.GetStoragePriceInternal(chain.dao) - require.Equal(t, int64(native.StoragePrice), n) + require.Equal(t, int64(native.DefaultStoragePrice), n) }) - testGetSet(t, chain, chain.contracts.Policy.Hash, "StoragePrice", native.StoragePrice, 1, 10000000) + testGetSet(t, chain, chain.contracts.Policy.Hash, "StoragePrice", native.DefaultStoragePrice, 1, 10000000) } func TestBlockedAccounts(t *testing.T) { diff --git a/pkg/core/oracle_test.go b/pkg/core/oracle_test.go index 45f55ca46..8545bf3fa 100644 --- a/pkg/core/oracle_test.go +++ b/pkg/core/oracle_test.go @@ -165,26 +165,26 @@ func TestOracle(t *testing.T) { t.Run("NormalRequest", func(t *testing.T) { resp := &transaction.OracleResponse{ - ID: 1, + ID: 0, Code: transaction.Success, Result: []byte{1, 2, 3, 4}, } - req := checkResp(t, 1, resp) + req := checkResp(t, 0, resp) - reqs := map[uint64]*state.OracleRequest{1: req} + reqs := map[uint64]*state.OracleRequest{0: req} orc2.ProcessRequestsInternal(reqs) - require.Equal(t, resp, m2[1].resp) + require.Equal(t, resp, m2[0].resp) require.Empty(t, ch2) t.Run("InvalidSignature", func(t *testing.T) { - orc1.AddResponse(acc2.PrivateKey().PublicKey(), m2[1].resp.ID, []byte{1, 2, 3}) + orc1.AddResponse(acc2.PrivateKey().PublicKey(), m2[0].resp.ID, []byte{1, 2, 3}) require.Empty(t, ch1) }) - orc1.AddResponse(acc2.PrivateKey().PublicKey(), m2[1].resp.ID, m2[1].txSig) + orc1.AddResponse(acc2.PrivateKey().PublicKey(), m2[0].resp.ID, m2[0].txSig) checkEmitTx(t, ch1) t.Run("FirstOtherThenMe", func(t *testing.T) { - const reqID = 2 + const reqID = 1 resp := &transaction.OracleResponse{ ID: reqID, @@ -203,58 +203,58 @@ func TestOracle(t *testing.T) { }) t.Run("Invalid", func(t *testing.T) { t.Run("Timeout", func(t *testing.T) { - checkResp(t, 3, &transaction.OracleResponse{ - ID: 3, + checkResp(t, 2, &transaction.OracleResponse{ + ID: 2, Code: transaction.Timeout, }) }) t.Run("NotFound", func(t *testing.T) { - checkResp(t, 4, &transaction.OracleResponse{ - ID: 4, + checkResp(t, 3, &transaction.OracleResponse{ + ID: 3, Code: transaction.NotFound, }) }) t.Run("Forbidden", func(t *testing.T) { + checkResp(t, 4, &transaction.OracleResponse{ + ID: 4, + Code: transaction.Forbidden, + }) + }) + t.Run("PrivateNetwork", func(t *testing.T) { checkResp(t, 5, &transaction.OracleResponse{ ID: 5, Code: transaction.Forbidden, }) }) - t.Run("PrivateNetwork", func(t *testing.T) { + t.Run("Big", func(t *testing.T) { checkResp(t, 6, &transaction.OracleResponse{ ID: 6, - Code: transaction.Forbidden, - }) - }) - t.Run("Big", func(t *testing.T) { - checkResp(t, 7, &transaction.OracleResponse{ - ID: 7, Code: transaction.ResponseTooLarge, }) }) t.Run("MaxAllowedSmallGAS", func(t *testing.T) { - checkResp(t, 8, &transaction.OracleResponse{ - ID: 8, + checkResp(t, 7, &transaction.OracleResponse{ + ID: 7, Code: transaction.InsufficientFunds, }) }) }) t.Run("MaxAllowedEnoughGAS", func(t *testing.T) { - checkResp(t, 9, &transaction.OracleResponse{ - ID: 9, + checkResp(t, 8, &transaction.OracleResponse{ + ID: 8, Code: transaction.Success, Result: make([]byte, transaction.MaxOracleResultSize), }) }) t.Run("WithFilter", func(t *testing.T) { - checkResp(t, 10, &transaction.OracleResponse{ - ID: 10, + checkResp(t, 9, &transaction.OracleResponse{ + ID: 9, Code: transaction.Success, Result: []byte(`[2]`), }) t.Run("invalid response", func(t *testing.T) { - checkResp(t, 11, &transaction.OracleResponse{ - ID: 11, + checkResp(t, 10, &transaction.OracleResponse{ + ID: 10, Code: transaction.Error, }) }) From 6a4e312eac8db705630fded7d262b3d0e70cdf47 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Fri, 5 Feb 2021 11:25:22 +0300 Subject: [PATCH 2/5] core: move GetPrice from `core` to `interop` We have additional logic for getting BaseExecFee policy value. This logic should be moved to interop context instead of being in Policer, because Policer is just an interface over Policy contract. After moving this logic to interop context, we need to use it to define BaseExecFee instead of (Policer).BaseExecFee. Thus, moving (*Blockchain).GetPrice to (*Context).GetPrice is necessary. --- pkg/core/blockchain.go | 11 ++++------- pkg/core/fee/calculate.go | 8 +++++--- pkg/core/gas_price.go | 12 ------------ pkg/core/interop/context.go | 2 +- pkg/core/interop/crypto/ecdsa.go | 6 ++---- pkg/core/interop/crypto/ecdsa_test.go | 3 ++- pkg/core/interop/gas_price.go | 11 +++++++++++ pkg/core/interops.go | 5 +++-- pkg/rpc/server/server_test.go | 2 +- pkg/vm/vm.go | 6 +++--- pkg/vm/vm_test.go | 2 +- 11 files changed, 33 insertions(+), 35 deletions(-) delete mode 100644 pkg/core/gas_price.go create mode 100644 pkg/core/interop/gas_price.go diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 93000f95f..b516e1ff4 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -641,7 +641,7 @@ func (bc *Blockchain) storeBlock(block *block.Block, txpool *mempool.Pool) error systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx) v := systemInterop.SpawnVM() v.LoadScriptWithFlags(tx.Script, callflag.All) - v.SetPriceGetter(bc.getPrice) + v.SetPriceGetter(systemInterop.GetPrice) v.LoadToken = contract.LoadToken(systemInterop) v.GasLimit = tx.SystemFee @@ -849,7 +849,7 @@ func (bc *Blockchain) runPersist(script []byte, block *block.Block, cache *dao.C systemInterop := bc.newInteropContext(trig, cache, block, nil) v := systemInterop.SpawnVM() v.LoadScriptWithFlags(script, callflag.WriteStates|callflag.AllowCall) - v.SetPriceGetter(bc.getPrice) + v.SetPriceGetter(systemInterop.GetPrice) if err := v.Run(); err != nil { return nil, fmt.Errorf("VM has failed: %w", err) } else if _, err := systemInterop.DAO.Persist(); err != nil { @@ -1718,7 +1718,7 @@ func (bc *Blockchain) GetTestVM(t trigger.Type, tx *transaction.Transaction, b * d.MPT = nil systemInterop := bc.newInteropContext(t, d, b, tx) vm := systemInterop.SpawnVM() - vm.SetPriceGetter(bc.getPrice) + vm.SetPriceGetter(systemInterop.GetPrice) vm.LoadToken = contract.LoadToken(systemInterop) return vm } @@ -1794,7 +1794,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa } vm := interopCtx.SpawnVM() - vm.SetPriceGetter(bc.getPrice) + vm.SetPriceGetter(interopCtx.GetPrice) vm.LoadToken = contract.LoadToken(interopCtx) vm.GasLimit = gas if err := bc.initVerificationVM(interopCtx, hash, witness); err != nil { @@ -1918,9 +1918,6 @@ func (bc *Blockchain) GetPolicer() blockchainer.Policer { // GetBaseExecFee return execution price for `NOP`. func (bc *Blockchain) GetBaseExecFee() int64 { - if bc.BlockHeight() == 0 { - return interop.DefaultBaseExecFee - } return bc.contracts.Policy.GetExecFeeFactorInternal(bc.dao) } diff --git a/pkg/core/fee/calculate.go b/pkg/core/fee/calculate.go index 0cf4e6383..4966ad4f5 100644 --- a/pkg/core/fee/calculate.go +++ b/pkg/core/fee/calculate.go @@ -1,13 +1,15 @@ package fee import ( - "github.com/nspcc-dev/neo-go/pkg/core/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" ) +// ECDSAVerifyPrice is a gas price of a single verification. +const ECDSAVerifyPrice = 1 << 15 + // Calculate returns network fee for transaction func Calculate(base int64, script []byte) (int64, int) { var ( @@ -16,13 +18,13 @@ func Calculate(base int64, script []byte) (int64, int) { ) if vm.IsSignatureContract(script) { size += 67 + io.GetVarSize(script) - netFee += Opcode(base, opcode.PUSHDATA1, opcode.PUSHNULL, opcode.PUSHDATA1) + base*crypto.ECDSAVerifyPrice + netFee += Opcode(base, opcode.PUSHDATA1, opcode.PUSHNULL, opcode.PUSHDATA1) + base*ECDSAVerifyPrice } else if m, pubs, ok := vm.ParseMultiSigContract(script); ok { n := len(pubs) sizeInv := 66 * m size += io.GetVarSize(sizeInv) + sizeInv + io.GetVarSize(script) netFee += calculateMultisig(base, m) + calculateMultisig(base, n) - netFee += Opcode(base, opcode.PUSHNULL) + base*crypto.ECDSAVerifyPrice*int64(n) + netFee += Opcode(base, opcode.PUSHNULL) + base*ECDSAVerifyPrice*int64(n) } else { // We can support more contract types in the future. } diff --git a/pkg/core/gas_price.go b/pkg/core/gas_price.go deleted file mode 100644 index 406e1e65a..000000000 --- a/pkg/core/gas_price.go +++ /dev/null @@ -1,12 +0,0 @@ -package core - -import ( - "github.com/nspcc-dev/neo-go/pkg/core/fee" - "github.com/nspcc-dev/neo-go/pkg/vm" - "github.com/nspcc-dev/neo-go/pkg/vm/opcode" -) - -// getPrice returns a price for executing op with the provided parameter. -func (bc *Blockchain) getPrice(v *vm.VM, op opcode.Opcode, parameter []byte) int64 { - return fee.Opcode(bc.GetBaseExecFee(), op) -} diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index 5cd231150..0d00d3e10 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -199,7 +199,7 @@ func (ic *Context) GetFunction(id uint32) *Function { // BaseExecFee represents factor to multiply syscall prices with. func (ic *Context) BaseExecFee() int64 { - if ic.Chain == nil { + if ic.Chain == nil || (ic.Block != nil && ic.Block.Index == 0) { return DefaultBaseExecFee } return ic.Chain.GetPolicer().GetBaseExecFee() diff --git a/pkg/core/interop/crypto/ecdsa.go b/pkg/core/interop/crypto/ecdsa.go index 3e27810af..a31ca3e70 100644 --- a/pkg/core/interop/crypto/ecdsa.go +++ b/pkg/core/interop/crypto/ecdsa.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/btcsuite/btcd/btcec" + "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/crypto" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" @@ -15,9 +16,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" ) -// ECDSAVerifyPrice is a gas price of a single verification. -const ECDSAVerifyPrice = 1 << 15 - // ECDSASecp256r1Verify checks ECDSA signature using Secp256r1 elliptic curve. func ECDSASecp256r1Verify(ic *interop.Context) error { return ecdsaVerify(ic, elliptic.P256()) @@ -69,7 +67,7 @@ func ecdsaCheckMultisig(ic *interop.Context, curve elliptic.Curve) error { if err != nil { return fmt.Errorf("wrong parameters: %w", err) } - if !ic.VM.AddGas(ic.BaseExecFee() * ECDSAVerifyPrice * int64(len(pkeys))) { + if !ic.VM.AddGas(ic.BaseExecFee() * fee.ECDSAVerifyPrice * int64(len(pkeys))) { return errors.New("gas limit exceeded") } sigs, err := ic.VM.Estack().PopSigElements() diff --git a/pkg/core/interop/crypto/ecdsa_test.go b/pkg/core/interop/crypto/ecdsa_test.go index 58fab77d6..1939514f2 100644 --- a/pkg/core/interop/crypto/ecdsa_test.go +++ b/pkg/core/interop/crypto/ecdsa_test.go @@ -7,6 +7,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/config/netmode" "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/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -247,7 +248,7 @@ func testCurveCHECKMULTISIGBad(t *testing.T, isR1 bool) { t.Run("1_2 too many signatures", func(t *testing.T) { testCHECKMULTISIGBad(t, isR1, true, 2, []int{0}, []int{0, 1}) }) t.Run("gas limit exceeded", func(t *testing.T) { v := initCHECKMULTISIGVM(t, isR1, 1, []int{0}, []int{0}) - v.GasLimit = ECDSAVerifyPrice - 1 + v.GasLimit = fee.ECDSAVerifyPrice - 1 require.Error(t, v.Run()) }) diff --git a/pkg/core/interop/gas_price.go b/pkg/core/interop/gas_price.go new file mode 100644 index 000000000..c72671411 --- /dev/null +++ b/pkg/core/interop/gas_price.go @@ -0,0 +1,11 @@ +package interop + +import ( + "github.com/nspcc-dev/neo-go/pkg/core/fee" + "github.com/nspcc-dev/neo-go/pkg/vm/opcode" +) + +// GetPrice returns a price for executing op with the provided parameter. +func (ic *Context) GetPrice(op opcode.Opcode, parameter []byte) int64 { + return fee.Opcode(ic.BaseExecFee(), op) +} diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 08dccd64d..d210ca97b 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -8,6 +8,7 @@ package core */ import ( + "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/binary" "github.com/nspcc-dev/neo-go/pkg/core/interop/contract" @@ -98,9 +99,9 @@ var systemInterops = []interop.Function{ var neoInterops = []interop.Function{ {Name: interopnames.NeoCryptoVerifyWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1Verify, - Price: crypto.ECDSAVerifyPrice, ParamCount: 3}, + Price: fee.ECDSAVerifyPrice, ParamCount: 3}, {Name: interopnames.NeoCryptoVerifyWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1Verify, - Price: crypto.ECDSAVerifyPrice, ParamCount: 3}, + Price: fee.ECDSAVerifyPrice, ParamCount: 3}, {Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256r1, Func: crypto.ECDSASecp256r1CheckMultisig, Price: 0, ParamCount: 3}, {Name: interopnames.NeoCryptoCheckMultisigWithECDsaSecp256k1, Func: crypto.ECDSASecp256k1CheckMultisig, Price: 0, ParamCount: 3}, {Name: interopnames.NeoCryptoSHA256, Func: crypto.Sha256, Price: 1 << 15, ParamCount: 1}, diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index a2da8e512..efe2a5f89 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -28,9 +28,9 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" - rpc2 "github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster" "github.com/nspcc-dev/neo-go/pkg/rpc/response" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" + rpc2 "github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index a1112a7b4..67f3b1f0c 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -65,7 +65,7 @@ type VM struct { state State // callback to get interop price - getPrice func(*VM, opcode.Opcode, []byte) int64 + getPrice func(opcode.Opcode, []byte) int64 istack *Stack // invocation stack. estack *Stack // execution stack. @@ -119,7 +119,7 @@ func (v *VM) newItemStack(n string) *Stack { // SetPriceGetter registers the given PriceGetterFunc in v. // f accepts vm's Context, current instruction and instruction parameter. -func (v *VM) SetPriceGetter(f func(*VM, opcode.Opcode, []byte) int64) { +func (v *VM) SetPriceGetter(f func(opcode.Opcode, []byte) int64) { v.getPrice = f } @@ -528,7 +528,7 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro }() if v.getPrice != nil && ctx.ip < len(ctx.prog) { - v.gasConsumed += v.getPrice(v, op, parameter) + v.gasConsumed += v.getPrice(op, parameter) if v.GasLimit >= 0 && v.gasConsumed > v.GasLimit { panic("gas limit is exceeded") } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 3dcf0d652..281441f1c 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -62,7 +62,7 @@ func TestVM_SetPriceGetter(t *testing.T) { require.EqualValues(t, 0, v.GasConsumed()) }) - v.SetPriceGetter(func(_ *VM, op opcode.Opcode, p []byte) int64 { + v.SetPriceGetter(func(op opcode.Opcode, p []byte) int64 { if op == opcode.PUSH4 { return 1 } else if op == opcode.PUSHDATA1 && bytes.Equal(p, []byte{0xCA, 0xFE}) { From 12f7111ca8cbafb4568b65d516340de393891b76 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 4 Feb 2021 12:19:04 +0300 Subject: [PATCH 3/5] core: mark blocked accounts with empty byte array --- pkg/core/native/policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/core/native/policy.go b/pkg/core/native/policy.go index 79a9edf40..aa0e9e651 100644 --- a/pkg/core/native/policy.go +++ b/pkg/core/native/policy.go @@ -490,7 +490,7 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki p.lock.Lock() defer p.lock.Unlock() err := ic.DAO.PutStorageItem(p.ContractID, key, &state.StorageItem{ - Value: []byte{0x01}, + Value: []byte{}, }) if err != nil { panic(err) From 2b066016462abc90bec064509bd151c8c992b9e4 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Wed, 3 Feb 2021 17:02:36 +0300 Subject: [PATCH 4/5] core: change Oracle request ID endianness --- pkg/core/native/oracle.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/core/native/oracle.go b/pkg/core/native/oracle.go index 2ef566f68..1907b50e7 100644 --- a/pkg/core/native/oracle.go +++ b/pkg/core/native/oracle.go @@ -434,7 +434,7 @@ func (o *Oracle) getRequests(d dao.DAO) (map[uint64]*state.OracleRequest, error) if r.Err != nil { return nil, r.Err } - id := binary.LittleEndian.Uint64([]byte(k)) + id := binary.BigEndian.Uint64([]byte(k)) reqs[id] = req } return reqs, nil @@ -443,7 +443,7 @@ func (o *Oracle) getRequests(d dao.DAO) (map[uint64]*state.OracleRequest, error) func makeRequestKey(id uint64) []byte { k := make([]byte, 9) k[0] = prefixRequest[0] - binary.LittleEndian.PutUint64(k[1:], id) + binary.BigEndian.PutUint64(k[1:], id) return k } From b0563ad0d77449cad38f2ba8f9d535f7299e0e6c Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Thu, 4 Feb 2021 12:42:48 +0300 Subject: [PATCH 5/5] services: fix Oracle responces mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Solves the following problem: === RUN TestOracleFull logger.go:130: 2021-02-04T09:25:16.305Z INFO P2PNotaryRequestPayloadPool size is not set or wrong, setting default value {"P2PNotaryRequestPayloadPoolSize": 1000} logger.go:130: 2021-02-04T09:25:16.306Z INFO no storage version found! creating genesis block logger.go:130: 2021-02-04T09:25:27.687Z DEBUG done processing headers {"headerIndex": 1, "blockHeight": 0, "took": "2.413398ms"} logger.go:130: 2021-02-04T09:25:27.696Z DEBUG done processing headers {"headerIndex": 2, "blockHeight": 1, "took": "1.138196ms"} logger.go:130: 2021-02-04T09:25:28.680Z INFO blockchain persist completed {"persistedBlocks": 2, "persistedKeys": 173, "headerHeight": 2, "blockHeight": 2, "took": "166.793µs"} fatal error: sync: Unlock of unlocked RWMutex goroutine 6157 [running]: runtime.throw(0x115dfdb, 0x20) /usr/local/go/src/runtime/panic.go:1116 +0x72 fp=0xc000297ca0 sp=0xc000297c70 pc=0x44f432 sync.throw(0x115dfdb, 0x20) /usr/local/go/src/runtime/panic.go:1102 +0x35 fp=0xc000297cc0 sp=0xc000297ca0 pc=0x44f3b5 sync.(*RWMutex).Unlock(0xc000135300) /usr/local/go/src/sync/rwmutex.go:129 +0xf3 fp=0xc000297d00 sp=0xc000297cc0 pc=0x4a1ac3 github.com/nspcc-dev/neo-go/pkg/services/oracle.(*Oracle).Run(0xc000135180) /go/src/github.com/nspcc-dev/neo-go/pkg/services/oracle/oracle.go:189 +0x82b fp=0xc000297fd8 sp=0xc000297d00 pc=0xe13b0b runtime.goexit() /usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000297fe0 sp=0xc000297fd8 pc=0x4834d1 created by github.com/nspcc-dev/neo-go/pkg/core.TestOracleFull /go/src/github.com/nspcc-dev/neo-go/pkg/core/oracle_test.go:276 +0x3f1 --- pkg/services/oracle/oracle.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/oracle/oracle.go b/pkg/services/oracle/oracle.go index 3df90edc3..58e9d4b89 100644 --- a/pkg/services/oracle/oracle.go +++ b/pkg/services/oracle/oracle.go @@ -171,7 +171,7 @@ func (o *Oracle) Run() { return case <-tick.C: var reprocess []uint64 - o.respMtx.RLock() + o.respMtx.Lock() o.removed = make(map[uint64]bool) for id, incTx := range o.responses { incTx.RLock()