*: drop support for old on-chain assets

You no longer can transfer them, so creating/renewing/storing doesn't make
much sense.
This commit is contained in:
Roman Khimov 2020-06-05 18:42:58 +03:00
parent bf6435eeaa
commit a986e2a064
20 changed files with 1 additions and 714 deletions

View file

@ -40,7 +40,6 @@ var syscalls = map[string]map[string]string{
},
"blockchain": {
"GetAccount": "Neo.Blockchain.GetAccount",
"GetAsset": "Neo.Blockchain.GetAsset",
"GetBlock": "Neo.Blockchain.GetBlock",
"GetContract": "Neo.Blockchain.GetContract",
"GetHeader": "Neo.Blockchain.GetHeader",
@ -69,18 +68,6 @@ var syscalls = map[string]map[string]string{
"GetHash": "Neo.Transaction.GetHash",
"GetWitnesses": "Neo.Transaction.GetWitnesses",
},
"asset": {
"Create": "Neo.Asset.Create",
"GetAdmin": "Neo.Asset.GetAdmin",
"GetAmount": "Neo.Asset.GetAmount",
"GetAssetID": "Neo.Asset.GetAssetID",
"GetAssetType": "Neo.Asset.GetAssetType",
"GetAvailable": "Neo.Asset.GetAvailable",
"GetIssuer": "Neo.Asset.GetIssuer",
"GetOwner": "Neo.Asset.GetOwner",
"GetPrecision": "Neo.Asset.GetPrecision",
"Renew": "Neo.Asset.Renew",
},
"contract": {
"GetScript": "Neo.Contract.GetScript",
"IsPayable": "Neo.Contract.IsPayable",

View file

@ -938,17 +938,6 @@ func (bc *Blockchain) HeaderHeight() uint32 {
return uint32(bc.headerListLen() - 1)
}
// GetAssetState returns asset state from its assetID.
func (bc *Blockchain) GetAssetState(assetID util.Uint256) *state.Asset {
asset, err := bc.dao.GetAssetState(assetID)
if asset == nil && err != storage.ErrKeyNotFound {
bc.log.Warn("failed to get asset state",
zap.Stringer("asset", assetID),
zap.Error(err))
}
return asset
}
// GetContractState returns contract by its script hash.
func (bc *Blockchain) GetContractState(hash util.Uint160) *state.Contract {
contract, err := bc.dao.GetContractState(hash)

View file

@ -32,7 +32,6 @@ type Blockchainer interface {
CurrentBlockHash() util.Uint256
HasBlock(util.Uint256) bool
HasTransaction(util.Uint256) bool
GetAssetState(util.Uint256) *state.Asset
GetAccountState(util.Uint160) *state.Account
GetAppExecResult(util.Uint256) (*state.AppExecResult, error)
GetNEP5TransferLog(util.Uint160) *state.NEP5TransferLog

View file

@ -23,7 +23,6 @@ type DAO interface {
GetAccountStateOrNew(hash util.Uint160) (*state.Account, error)
GetAndDecode(entity io.Serializable, key []byte) error
GetAppExecResult(hash util.Uint256) (*state.AppExecResult, error)
GetAssetState(assetID util.Uint256) (*state.Asset, error)
GetBatch() *storage.MemBatch
GetBlock(hash util.Uint256) (*block.Block, error)
GetContractState(hash util.Uint160) (*state.Contract, error)
@ -42,7 +41,6 @@ type DAO interface {
Persist() (int, error)
PutAccountState(as *state.Account) error
PutAppExecResult(aer *state.AppExecResult) error
PutAssetState(as *state.Asset) error
PutContractState(cs *state.Contract) error
PutCurrentHeader(hashAndIndex []byte) error
PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error
@ -141,30 +139,6 @@ func (dao *Simple) putAccountState(as *state.Account, buf *io.BufBinWriter) erro
// -- end accounts.
// -- start assets.
// GetAssetState returns given asset state as recorded in the given store.
func (dao *Simple) GetAssetState(assetID util.Uint256) (*state.Asset, error) {
asset := &state.Asset{}
key := storage.AppendPrefix(storage.STAsset, assetID.BytesBE())
err := dao.GetAndDecode(asset, key)
if err != nil {
return nil, err
}
if asset.ID != assetID {
return nil, fmt.Errorf("found asset id is not equal to expected")
}
return asset, nil
}
// PutAssetState puts given asset state into the given store.
func (dao *Simple) PutAssetState(as *state.Asset) error {
key := storage.AppendPrefix(storage.STAsset, as.ID.BytesBE())
return dao.Put(as, key)
}
// -- end assets.
// -- start contracts.
// GetContractState returns contract state as recorded in the given

View file

@ -7,7 +7,6 @@ import (
"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/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/internal/random"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -59,17 +58,6 @@ func TestPutAndGetAccountStateOrNew(t *testing.T) {
require.Equal(t, accountState.ScriptHash, gotAccount.ScriptHash)
}
func TestPutAndGetAssetState(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
id := random.Uint256()
assetState := &state.Asset{ID: id, Owner: keys.PublicKey{}}
err := dao.PutAssetState(assetState)
require.NoError(t, err)
gotAssetState, err := dao.GetAssetState(id)
require.NoError(t, err)
require.Equal(t, assetState, gotAssetState)
}
func TestPutAndGetContractState(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore())
contractState := &state.Contract{Script: []byte{}, ParamList: []smartcontract.ParamType{}}

View file

@ -41,10 +41,6 @@ func getSyscallPrice(v *vm.VM, id uint32) util.Fixed8 {
}
const (
neoAssetCreate = 0x1fc6c583 // Neo.Asset.Create
antSharesAssetCreate = 0x99025068 // AntShares.Asset.Create
neoAssetRenew = 0x71908478 // Neo.Asset.Renew
antSharesAssetRenew = 0xaf22447b // AntShares.Asset.Renew
neoContractCreate = 0x6ea56cf6 // Neo.Contract.Create
neoContractMigrate = 0x90621b47 // Neo.Contract.Migrate
antSharesContractCreate = 0x2a28d29b // AntShares.Contract.Create
@ -58,11 +54,6 @@ func getSyscallPrice(v *vm.VM, id uint32) util.Fixed8 {
estack := v.Estack()
switch id {
case neoAssetCreate, antSharesAssetCreate:
return util.Fixed8FromInt64(5000)
case neoAssetRenew, antSharesAssetRenew:
arg := estack.Peek(1).BigInt().Int64()
return util.Fixed8FromInt64(arg * 5000)
case neoContractCreate, neoContractMigrate, antSharesContractCreate, antSharesContractMigrate:
return smartcontract.GetDeploymentPrice(smartcontract.PropertyState(estack.Peek(3).BigInt().Int64()))
case systemStoragePut, systemStoragePutEx, neoStoragePut, antSharesStoragePut:

View file

@ -23,21 +23,6 @@ func TestGetPrice(t *testing.T) {
v := SpawnVM(systemInterop)
v.SetPriceGetter(getPrice)
t.Run("Neo.Asset.Create", func(t *testing.T) {
// Neo.Asset.Create: 83c5c61f
v.Load([]byte{byte(opcode.SYSCALL), 0x83, 0xc5, 0xc6, 0x1f})
checkGas(t, util.Fixed8FromInt64(5000), v)
})
t.Run("Neo.Asset.Renew", func(t *testing.T) {
// Neo.Asset.Renew: 78849071 (requires push 09 push 09 before)
v.Load([]byte{byte(opcode.PUSH9), byte(opcode.PUSH9), byte(opcode.SYSCALL), 0x78, 0x84, 0x90, 0x71})
require.NoError(t, v.StepInto()) // push 9
require.NoError(t, v.StepInto()) // push 9
checkGas(t, util.Fixed8FromInt64(9*5000), v)
})
t.Run("Neo.Contract.Create (no props)", func(t *testing.T) {
// Neo.Contract.Create: f66ca56e (requires push properties on fourth position)
v.Load([]byte{byte(opcode.PUSH0), byte(opcode.PUSH0), byte(opcode.PUSH0), byte(opcode.PUSH0),

View file

@ -4,19 +4,15 @@ import (
"bytes"
"errors"
"fmt"
"math"
"sort"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"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"
gherr "github.com/pkg/errors"
)
const (
@ -28,15 +24,6 @@ const (
MaxContractParametersNum = 252
// MaxContractStringLen is the maximum length for contract metadata strings.
MaxContractStringLen = 252
// MaxAssetNameLen is the maximum length of asset name.
MaxAssetNameLen = 1024
// MaxAssetPrecision is the maximum precision of asset.
MaxAssetPrecision = 8
// BlocksPerYear is a multiplier for asset renewal.
BlocksPerYear = 2000000
// DefaultAssetLifetime is the default lifetime of an asset (which differs
// from assets created by register tx).
DefaultAssetLifetime = 1 + BlocksPerYear
)
// headerGetVersion returns version from the header.
@ -156,21 +143,6 @@ func bcGetAccount(ic *interop.Context, v *vm.VM) error {
return nil
}
// bcGetAsset returns an asset.
func bcGetAsset(ic *interop.Context, v *vm.VM) error {
asbytes := v.Estack().Pop().Bytes()
ashash, err := util.Uint256DecodeBytesBE(asbytes)
if err != nil {
return err
}
as, err := ic.DAO.GetAssetState(ashash)
if err != nil {
return errors.New("asset not found")
}
v.Estack().PushVal(vm.NewInteropItem(as))
return nil
}
// accountGetBalance returns balance for a given account.
func accountGetBalance(ic *interop.Context, v *vm.VM) error {
accInterface := v.Estack().Pop().Value()
@ -374,203 +346,6 @@ func contractMigrate(ic *interop.Context, v *vm.VM) error {
return contractDestroy(ic, v)
}
// assetCreate creates an asset.
func assetCreate(ic *interop.Context, v *vm.VM) error {
if ic.Trigger != trigger.Application {
return errors.New("can't create asset when not triggered by an application")
}
atype := transaction.AssetType(v.Estack().Pop().BigInt().Int64())
switch atype {
case transaction.Currency, transaction.Share, transaction.Invoice, transaction.Token:
// ok
default:
return fmt.Errorf("wrong asset type: %x", atype)
}
name := string(v.Estack().Pop().Bytes())
if len(name) > MaxAssetNameLen {
return errors.New("too big name")
}
amount := util.Fixed8(v.Estack().Pop().BigInt().Int64())
if amount == util.Fixed8(0) {
return errors.New("asset amount can't be zero")
}
if amount < -util.Satoshi() {
return errors.New("asset amount can't be negative (except special -Satoshi value")
}
if atype == transaction.Invoice && amount != -util.Satoshi() {
return errors.New("invoice assets can only have -Satoshi amount")
}
precision := byte(v.Estack().Pop().BigInt().Int64())
if precision > MaxAssetPrecision {
return fmt.Errorf("can't have asset precision of more than %d", MaxAssetPrecision)
}
if atype == transaction.Share && precision != 0 {
return errors.New("share assets can only have zero precision")
}
if amount != -util.Satoshi() && (int64(amount)%int64(math.Pow10(int(MaxAssetPrecision-precision))) != 0) {
return errors.New("given asset amount has fractional component")
}
owner, err := keys.NewPublicKeyFromBytes(v.Estack().Pop().Bytes())
if err != nil {
return gherr.Wrap(err, "failed to get owner key")
}
if owner.IsInfinity() {
return errors.New("can't have infinity as an owner key")
}
witnessOk, err := runtime.CheckKeyedWitness(ic, v, owner)
if err != nil {
return err
}
if !witnessOk {
return errors.New("witness check didn't succeed")
}
admin, err := util.Uint160DecodeBytesBE(v.Estack().Pop().Bytes())
if err != nil {
return gherr.Wrap(err, "failed to get admin")
}
issuer, err := util.Uint160DecodeBytesBE(v.Estack().Pop().Bytes())
if err != nil {
return gherr.Wrap(err, "failed to get issuer")
}
asset := &state.Asset{
ID: ic.Tx.Hash(),
AssetType: atype,
Name: name,
Amount: amount,
Precision: precision,
Owner: *owner,
Admin: admin,
Issuer: issuer,
Expiration: ic.Chain.BlockHeight() + DefaultAssetLifetime,
}
err = ic.DAO.PutAssetState(asset)
if err != nil {
return gherr.Wrap(err, "failed to Store asset")
}
v.Estack().PushVal(vm.NewInteropItem(asset))
return nil
}
// assetGetAdmin returns asset admin.
func assetGetAdmin(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(as.Admin.BytesBE())
return nil
}
// assetGetAmount returns the overall amount of asset available.
func assetGetAmount(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(int64(as.Amount))
return nil
}
// assetGetAssetId returns the id of an asset.
func assetGetAssetID(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(as.ID.BytesBE())
return nil
}
// assetGetAssetType returns type of an asset.
func assetGetAssetType(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(int(as.AssetType))
return nil
}
// assetGetAvailable returns available (not yet issued) amount of asset.
func assetGetAvailable(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(int(as.Available))
return nil
}
// assetGetIssuer returns issuer of an asset.
func assetGetIssuer(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(as.Issuer.BytesBE())
return nil
}
// assetGetOwner returns owner of an asset.
func assetGetOwner(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(as.Owner.Bytes())
return nil
}
// assetGetPrecision returns precision used to measure this asset.
func assetGetPrecision(ic *interop.Context, v *vm.VM) error {
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
v.Estack().PushVal(int(as.Precision))
return nil
}
// assetRenew updates asset expiration date.
func assetRenew(ic *interop.Context, v *vm.VM) error {
if ic.Trigger != trigger.Application {
return errors.New("can't create asset when not triggered by an application")
}
asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset)
if !ok {
return fmt.Errorf("%T is not an asset state", as)
}
years := byte(v.Estack().Pop().BigInt().Int64())
// Not sure why C# code regets an asset from the Store, but we also do it.
asset, err := ic.DAO.GetAssetState(as.ID)
if err != nil {
return errors.New("can't renew non-existent asset")
}
if asset.Expiration < ic.Chain.BlockHeight()+1 {
asset.Expiration = ic.Chain.BlockHeight() + 1
}
expiration := uint64(asset.Expiration) + uint64(years)*BlocksPerYear
if expiration > math.MaxUint32 {
expiration = math.MaxUint32
}
asset.Expiration = uint32(expiration)
err = ic.DAO.PutAssetState(asset)
if err != nil {
return gherr.Wrap(err, "failed to Store asset")
}
v.Estack().PushVal(expiration)
return nil
}
// runtimeSerialize serializes top stack item into a ByteArray.
func runtimeSerialize(_ *interop.Context, v *vm.VM) error {
return vm.RuntimeSerialize(v)

View file

@ -27,14 +27,11 @@ import (
/* Missing tests:
* TestTxGetWitnesses
* TestBcGetAccount
* TestBcGetAsset
* TestAccountGetBalance
* TestAccountIsStandard
* TestCreateContractStateFromVM
* TestContractCreate
* TestContractMigrate
* TestAssetCreate
* TestAssetRenew
* TestRuntimeSerialize
* TestRuntimeDeserialize
*/
@ -337,95 +334,7 @@ func TestContractIsPayable(t *testing.T) {
require.Equal(t, contractState.IsPayable(), isPayable)
}
func TestAssetGetAdmin(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetAdmin(context, v)
require.NoError(t, err)
admin := v.Estack().Pop().Value()
require.Equal(t, assetState.Admin.BytesBE(), admin)
}
func TestAssetGetAmount(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetAmount(context, v)
require.NoError(t, err)
amount := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.Amount)), amount)
}
func TestAssetGetAssetID(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetAssetID(context, v)
require.NoError(t, err)
assetID := v.Estack().Pop().Value()
require.Equal(t, assetState.ID.BytesBE(), assetID)
}
func TestAssetGetAssetType(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetAssetType(context, v)
require.NoError(t, err)
assetType := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.AssetType)), assetType)
}
func TestAssetGetAvailable(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetAvailable(context, v)
require.NoError(t, err)
available := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.Available)), available)
}
func TestAssetGetIssuer(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetIssuer(context, v)
require.NoError(t, err)
issuer := v.Estack().Pop().Value()
require.Equal(t, assetState.Issuer.BytesBE(), issuer)
}
func TestAssetGetOwner(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetOwner(context, v)
require.NoError(t, err)
owner := v.Estack().Pop().Value()
require.Equal(t, assetState.Owner.Bytes(), owner)
}
func TestAssetGetPrecision(t *testing.T) {
v, assetState, context, chain := createVMAndAssetState(t)
defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState))
err := assetGetPrecision(context, v)
require.NoError(t, err)
precision := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.Precision)), precision)
}
// Helper functions to create VM, InteropContext, TX, Account, Contract, Asset.
// Helper functions to create VM, InteropContext, TX, Account, Contract.
func createVMAndPushBlock(t *testing.T) (*vm.VM, *block.Block, *interop.Context, *Blockchain) {
v := vm.New()
@ -442,29 +351,6 @@ func createVMAndPushTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop
return v, tx, context, chain
}
func createVMAndAssetState(t *testing.T) (*vm.VM, *state.Asset, *interop.Context, *Blockchain) {
v := vm.New()
assetState := &state.Asset{
ID: util.Uint256{},
AssetType: transaction.GoverningToken,
Name: "TestAsset",
Amount: 1,
Available: 2,
Precision: 1,
FeeMode: 1,
FeeAddress: random.Uint160(),
Owner: keys.PublicKey{X: big.NewInt(1), Y: big.NewInt(1)},
Admin: random.Uint160(),
Issuer: random.Uint160(),
Expiration: 10,
IsFrozen: false,
}
chain := newTestChain(t)
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
return v, assetState, context, chain
}
func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interop.Context, *Blockchain) {
v := vm.New()
contractState := &state.Contract{

View file

@ -105,23 +105,12 @@ var neoInterops = []interop.Function{
{Name: "Neo.Account.GetBalance", Func: accountGetBalance, Price: 1},
{Name: "Neo.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
{Name: "Neo.Account.IsStandard", Func: accountIsStandard, Price: 100},
{Name: "Neo.Asset.Create", Func: assetCreate, Price: 0},
{Name: "Neo.Asset.GetAdmin", Func: assetGetAdmin, Price: 1},
{Name: "Neo.Asset.GetAmount", Func: assetGetAmount, Price: 1},
{Name: "Neo.Asset.GetAssetId", Func: assetGetAssetID, Price: 1},
{Name: "Neo.Asset.GetAssetType", Func: assetGetAssetType, Price: 1},
{Name: "Neo.Asset.GetAvailable", Func: assetGetAvailable, Price: 1},
{Name: "Neo.Asset.GetIssuer", Func: assetGetIssuer, Price: 1},
{Name: "Neo.Asset.GetOwner", Func: assetGetOwner, Price: 1},
{Name: "Neo.Asset.GetPrecision", Func: assetGetPrecision, Price: 1},
{Name: "Neo.Asset.Renew", Func: assetRenew, Price: 0},
{Name: "Neo.Attribute.GetData", Func: attrGetData, Price: 1},
{Name: "Neo.Attribute.GetUsage", Func: attrGetUsage, Price: 1},
{Name: "Neo.Block.GetTransaction", Func: blockGetTransaction, Price: 1},
{Name: "Neo.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1},
{Name: "Neo.Block.GetTransactions", Func: blockGetTransactions, Price: 1},
{Name: "Neo.Blockchain.GetAccount", Func: bcGetAccount, Price: 100},
{Name: "Neo.Blockchain.GetAsset", Func: bcGetAsset, Price: 100},
{Name: "Neo.Blockchain.GetBlock", Func: bcGetBlock, Price: 200},
{Name: "Neo.Blockchain.GetContract", Func: bcGetContract, Price: 100},
{Name: "Neo.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
@ -180,23 +169,12 @@ var neoInterops = []interop.Function{
// Old compatibility APIs.
{Name: "AntShares.Account.GetBalance", Func: accountGetBalance, Price: 1},
{Name: "AntShares.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
{Name: "AntShares.Asset.Create", Func: assetCreate, Price: 0},
{Name: "AntShares.Asset.GetAdmin", Func: assetGetAdmin, Price: 1},
{Name: "AntShares.Asset.GetAmount", Func: assetGetAmount, Price: 1},
{Name: "AntShares.Asset.GetAssetId", Func: assetGetAssetID, Price: 1},
{Name: "AntShares.Asset.GetAssetType", Func: assetGetAssetType, Price: 1},
{Name: "AntShares.Asset.GetAvailable", Func: assetGetAvailable, Price: 1},
{Name: "AntShares.Asset.GetIssuer", Func: assetGetIssuer, Price: 1},
{Name: "AntShares.Asset.GetOwner", Func: assetGetOwner, Price: 1},
{Name: "AntShares.Asset.GetPrecision", Func: assetGetPrecision, Price: 1},
{Name: "AntShares.Asset.Renew", Func: assetRenew, Price: 0},
{Name: "AntShares.Attribute.GetData", Func: attrGetData, Price: 1},
{Name: "AntShares.Attribute.GetUsage", Func: attrGetUsage, Price: 1},
{Name: "AntShares.Block.GetTransaction", Func: blockGetTransaction, Price: 1},
{Name: "AntShares.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1},
{Name: "AntShares.Block.GetTransactions", Func: blockGetTransactions, Price: 1},
{Name: "AntShares.Blockchain.GetAccount", Func: bcGetAccount, Price: 100},
{Name: "AntShares.Blockchain.GetAsset", Func: bcGetAsset, Price: 100},
{Name: "AntShares.Blockchain.GetBlock", Func: bcGetBlock, Price: 200},
{Name: "AntShares.Blockchain.GetContract", Func: bcGetContract, Price: 100},
{Name: "AntShares.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},

View file

@ -34,15 +34,6 @@ func TestUnexpectedNonInterops(t *testing.T) {
funcs := []func(*interop.Context, *vm.VM) error{
accountGetBalance,
accountGetScriptHash,
assetGetAdmin,
assetGetAmount,
assetGetAssetID,
assetGetAssetType,
assetGetAvailable,
assetGetIssuer,
assetGetOwner,
assetGetPrecision,
assetRenew,
attrGetData,
attrGetUsage,
blockGetTransaction,

View file

@ -1,78 +0,0 @@
package state
import (
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
)
const feeMode = 0x0
// Asset represents the state of an NEO registered Asset.
type Asset struct {
ID util.Uint256
AssetType transaction.AssetType
Name string
Amount util.Fixed8
Available util.Fixed8
Precision uint8
FeeMode uint8
FeeAddress util.Uint160
Owner keys.PublicKey
Admin util.Uint160
Issuer util.Uint160
Expiration uint32
IsFrozen bool
}
// DecodeBinary implements Serializable interface.
func (a *Asset) DecodeBinary(br *io.BinReader) {
br.ReadBytes(a.ID[:])
a.AssetType = transaction.AssetType(br.ReadB())
a.Name = br.ReadString()
a.Amount.DecodeBinary(br)
a.Available.DecodeBinary(br)
a.Precision = uint8(br.ReadB())
a.FeeMode = uint8(br.ReadB())
a.FeeAddress.DecodeBinary(br)
a.Owner.DecodeBinary(br)
a.Admin.DecodeBinary(br)
a.Issuer.DecodeBinary(br)
a.Expiration = br.ReadU32LE()
a.IsFrozen = br.ReadBool()
}
// EncodeBinary implements Serializable interface.
func (a *Asset) EncodeBinary(bw *io.BinWriter) {
bw.WriteBytes(a.ID[:])
bw.WriteB(byte(a.AssetType))
bw.WriteString(a.Name)
a.Amount.EncodeBinary(bw)
a.Available.EncodeBinary(bw)
bw.WriteB(byte(a.Precision))
bw.WriteB(byte(a.FeeMode))
a.FeeAddress.EncodeBinary(bw)
a.Owner.EncodeBinary(bw)
a.Admin.EncodeBinary(bw)
a.Issuer.EncodeBinary(bw)
bw.WriteU32LE(a.Expiration)
bw.WriteBool(a.IsFrozen)
}
// GetName returns the asset name based on its type.
func (a *Asset) GetName() string {
if a.AssetType == transaction.GoverningToken {
return "NEO"
} else if a.AssetType == transaction.UtilityToken {
return "NEOGas"
}
return a.Name
}

View file

@ -1,41 +0,0 @@
package state
import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/internal/random"
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/stretchr/testify/assert"
)
func TestEncodeDecodeAssetState(t *testing.T) {
asset := &Asset{
ID: random.Uint256(),
AssetType: transaction.Token,
Name: "super cool token",
Amount: util.Fixed8(1000000),
Available: util.Fixed8(100),
Precision: 0,
FeeMode: feeMode,
Owner: keys.PublicKey{},
Admin: random.Uint160(),
Issuer: random.Uint160(),
Expiration: 10,
IsFrozen: false,
}
testserdes.EncodeDecodeBinary(t, asset, new(Asset))
}
func TestAssetState_GetName_NEO(t *testing.T) {
asset := &Asset{AssetType: transaction.GoverningToken}
assert.Equal(t, "NEO", asset.GetName())
}
func TestAssetState_GetName_NEOGas(t *testing.T) {
asset := &Asset{AssetType: transaction.UtilityToken}
assert.Equal(t, "NEOGas", asset.GetName())
}

View file

@ -10,7 +10,6 @@ const (
DataBlock KeyPrefix = 0x01
DataTransaction KeyPrefix = 0x02
STAccount KeyPrefix = 0x40
STAsset KeyPrefix = 0x4c
STNotification KeyPrefix = 0x4d
STContract KeyPrefix = 0x50
STStorage KeyPrefix = 0x70

View file

@ -11,7 +11,6 @@ var (
DataBlock,
DataTransaction,
STAccount,
STAsset,
STContract,
STStorage,
IXHeaderHashList,
@ -24,7 +23,6 @@ var (
0x01,
0x02,
0x40,
0x4c,
0x50,
0x70,
0x80,

View file

@ -1,16 +0,0 @@
package transaction
// AssetType represents a NEO asset type.
type AssetType uint8
// Valid asset types.
const (
CreditFlag AssetType = 0x40
DutyFlag AssetType = 0x80
GoverningToken AssetType = 0x00
UtilityToken AssetType = 0x01
Currency AssetType = 0x08
Share AssetType = DutyFlag | 0x10
Invoice AssetType = DutyFlag | 0x18
Token AssetType = CreditFlag | 0x20
)

View file

@ -1,9 +0,0 @@
package transaction
import "github.com/nspcc-dev/neo-go/pkg/util"
// Result represents the Result of a transaction.
type Result struct {
AssetID util.Uint256
Amount util.Fixed8
}

View file

@ -1,97 +0,0 @@
/*
Package asset provides functions to work with regular UTXO assets (like NEO or GAS).
Mostly these are getters for Asset structure, but you can also create new assets
and renew them (although it's recommended to use NEP-5 standard for new tokens).
*/
package asset
// Asset represents NEO asset type that is used in interop functions, it's
// an opaque data structure that you can get data from only using functions from
// this package. It's similar in function to the Asset class in the Neo .net
// framework. To be able to use it you either need to get an existing Asset via
// blockchain.GetAsset function or create a new one via Create.
type Asset struct{}
// GetAssetID returns ID (256-bit ID of Register transaction for this asset in BE
// representation) of the given asset. It uses `Neo.Asset.GetAssetId` syscall
// internally.
func GetAssetID(a Asset) []byte {
return nil
}
// GetAssetType returns type of the given asset as a byte value. The value
// returned can be interpreted as a bit field with the following meaning:
// CreditFlag = 0x40
// DutyFlag = 0x80
// SystemShare = 0x00
// SystemCoin = 0x01
// Currency = 0x08
// Share = DutyFlag | 0x10
// Invoice = DutyFlag | 0x18
// Token = CreditFlag | 0x20
// It uses `Neo.Asset.GetAssetType` syscall internally.
func GetAssetType(a Asset) byte {
return 0x00
}
// GetAmount returns the total amount of the given asset as an integer
// multiplied by 10⁸. This value is the maximum possible circulating quantity of
// Asset. The function uses `Neo.Asset.GetAmount` syscall internally.
func GetAmount(a Asset) int {
return 0
}
// GetAvailable returns the amount of Asset currently available on the
// blockchain. It uses the same encoding as the result of GetAmount and its
// value can never exceed the value returned by GetAmount. This function uses
// `Neo.Asset.GetAvailable` syscall internally.
func GetAvailable(a Asset) int {
return 0
}
// GetPrecision returns precision of the given Asset. It uses
// `Neo.Asset.GetPrecision` syscall internally.
func GetPrecision(a Asset) byte {
return 0x00
}
// GetOwner returns the owner of the given Asset. It's represented as a
// serialized (in compressed form) public key (33 bytes long). This function
// uses `Neo.Asset.GetOwner` syscall internally.
func GetOwner(a Asset) []byte {
return nil
}
// GetAdmin returns the admin of the given Asset represented as a 160 bit hash
// in BE form (contract script hash). Admin can modify attributes of this Asset.
// This function uses `Neo.Asset.GetAdmin` syscall internally.
func GetAdmin(a Asset) []byte {
return nil
}
// GetIssuer returns the issuer of the given Asset represented as a 160 bit hash
// in BE form (contract script hash). Issuer can issue new tokens for this Asset.
// This function uses `Neo.Asset.GetIssuer` syscall internally.
func GetIssuer(a Asset) []byte {
return nil
}
// Create registers a new asset on the blockchain (similar to old Register
// transaction). `assetType` parameter has the same set of possible values as
// GetAssetType result, `amount` must be multiplied by 10⁸, `precision` limits
// the smallest possible amount of new Asset to 10⁻ⁿ (where n is precision which
// can't exceed 8), `owner` is a public key of the owner in compressed serialized
// form (33 bytes), `admin` and `issuer` should be represented as 20-byte slices
// storing 160-bit hash in BE form. Created Asset is set to expire in one year,
// so you need to renew it in time. If successful, this function returns a new
// Asset. It uses `Neo.Asset.Create` syscall internally.
func Create(assetType byte, name string, amount int, precision byte, owner, admin, issuer []byte) Asset {
return Asset{}
}
// Renew renews (make available for use) existing asset by the specified number
// of years. It returns the last block number when this asset will be active.
// It uses `Neo.Asset.Renew` syscall internally.
func Renew(asset Asset, years int) int {
return 0
}

View file

@ -5,7 +5,6 @@ package blockchain
import (
"github.com/nspcc-dev/neo-go/pkg/interop/account"
"github.com/nspcc-dev/neo-go/pkg/interop/asset"
"github.com/nspcc-dev/neo-go/pkg/interop/block"
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
"github.com/nspcc-dev/neo-go/pkg/interop/header"
@ -73,11 +72,3 @@ func GetAccount(scriptHash []byte) account.Account {
func GetValidators() [][]byte {
return nil
}
// GetAsset returns asset found by the given asset ID (256 bit in BE format
// represented as a slice of 32 bytes). Refer to the `asset` package for
// possible uses of returned structure. This function uses
// `Neo.Blockchain.GetAsset` syscall.
func GetAsset(assetID []byte) asset.Asset {
return asset.Asset{}
}

View file

@ -73,9 +73,6 @@ func (chain testChain) GetHeader(hash util.Uint256) (*block.Header, error) {
panic("TODO")
}
func (chain testChain) GetAssetState(util.Uint256) *state.Asset {
panic("TODO")
}
func (chain testChain) GetAccountState(util.Uint160) *state.Account {
panic("TODO")
}