core: update *.Contract.* interops
1. Remove GetScript, IsPayable, GetStorageContext.
2. Revert 82319538
related to GetStorageContext.
3. Rename Migrate to Update.
4. Move remaining to System.Contract.*.
Related #1031.
This commit is contained in:
parent
c69f8a2fa3
commit
f8a11f61b6
12 changed files with 18 additions and 119 deletions
|
@ -37,12 +37,9 @@ var syscalls = map[string]map[string]string{
|
||||||
"GetTransactionHeight": "System.Blockchain.GetTransactionHeight",
|
"GetTransactionHeight": "System.Blockchain.GetTransactionHeight",
|
||||||
},
|
},
|
||||||
"contract": {
|
"contract": {
|
||||||
"GetScript": "Neo.Contract.GetScript",
|
"Create": "System.Contract.Create",
|
||||||
"IsPayable": "Neo.Contract.IsPayable",
|
"Destroy": "System.Contract.Destroy",
|
||||||
"Create": "Neo.Contract.Create",
|
"Update": "System.Contract.Update",
|
||||||
"Destroy": "Neo.Contract.Destroy",
|
|
||||||
"Migrate": "Neo.Contract.Migrate",
|
|
||||||
"GetStorageContext": "Neo.Contract.GetStorageContext",
|
|
||||||
},
|
},
|
||||||
"engine": {
|
"engine": {
|
||||||
"GetScriptContainer": "System.ExecutionEngine.GetScriptContainer",
|
"GetScriptContainer": "System.ExecutionEngine.GetScriptContainer",
|
||||||
|
|
|
@ -236,7 +236,7 @@ func TestCreateBasicChain(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
emit.Bytes(script.BinWriter, bs)
|
emit.Bytes(script.BinWriter, bs)
|
||||||
emit.Bytes(script.BinWriter, avm)
|
emit.Bytes(script.BinWriter, avm)
|
||||||
emit.Syscall(script.BinWriter, "Neo.Contract.Create")
|
emit.Syscall(script.BinWriter, "System.Contract.Create")
|
||||||
txScript := script.Bytes()
|
txScript := script.Bytes()
|
||||||
|
|
||||||
invFee := util.Fixed8FromFloat(100)
|
invFee := util.Fixed8FromFloat(100)
|
||||||
|
|
|
@ -28,7 +28,6 @@ type Context struct {
|
||||||
Block *block.Block
|
Block *block.Block
|
||||||
Tx *transaction.Transaction
|
Tx *transaction.Transaction
|
||||||
DAO *dao.Cached
|
DAO *dao.Cached
|
||||||
LowerDAO dao.DAO
|
|
||||||
Notifications []state.NotificationEvent
|
Notifications []state.NotificationEvent
|
||||||
Log *zap.Logger
|
Log *zap.Logger
|
||||||
}
|
}
|
||||||
|
@ -44,7 +43,6 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO, n
|
||||||
Block: block,
|
Block: block,
|
||||||
Tx: tx,
|
Tx: tx,
|
||||||
DAO: dao,
|
DAO: dao,
|
||||||
LowerDAO: d,
|
|
||||||
Notifications: nes,
|
Notifications: nes,
|
||||||
Log: log,
|
Log: log,
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,30 +114,8 @@ func contractCreate(ic *interop.Context, v *vm.VM) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// contractGetScript returns a script associated with a contract.
|
// contractUpdate migrates a contract.
|
||||||
func contractGetScript(ic *interop.Context, v *vm.VM) error {
|
func contractUpdate(ic *interop.Context, v *vm.VM) error {
|
||||||
csInterface := v.Estack().Pop().Value()
|
|
||||||
cs, ok := csInterface.(*state.Contract)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%T is not a contract state", cs)
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(cs.Script)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// contractIsPayable returns whether contract is payable.
|
|
||||||
func contractIsPayable(ic *interop.Context, v *vm.VM) error {
|
|
||||||
csInterface := v.Estack().Pop().Value()
|
|
||||||
cs, ok := csInterface.(*state.Contract)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%T is not a contract state", cs)
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(cs.IsPayable())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// contractMigrate migrates a contract.
|
|
||||||
func contractMigrate(ic *interop.Context, v *vm.VM) error {
|
|
||||||
contract, err := ic.DAO.GetContractState(v.GetCurrentScriptHash())
|
contract, err := ic.DAO.GetContractState(v.GetCurrentScriptHash())
|
||||||
if contract == nil {
|
if contract == nil {
|
||||||
return errors.New("contract doesn't exist")
|
return errors.New("contract doesn't exist")
|
||||||
|
|
|
@ -212,28 +212,6 @@ func TestECDSAVerify(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContractGetScript(t *testing.T) {
|
|
||||||
v, contractState, context, chain := createVMAndContractState(t)
|
|
||||||
defer chain.Close()
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(contractState))
|
|
||||||
|
|
||||||
err := contractGetScript(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
script := v.Estack().Pop().Value()
|
|
||||||
require.Equal(t, contractState.Script, script)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContractIsPayable(t *testing.T) {
|
|
||||||
v, contractState, context, chain := createVMAndContractState(t)
|
|
||||||
defer chain.Close()
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(contractState))
|
|
||||||
|
|
||||||
err := contractIsPayable(context, v)
|
|
||||||
require.NoError(t, err)
|
|
||||||
isPayable := v.Estack().Pop().Value()
|
|
||||||
require.Equal(t, contractState.IsPayable(), isPayable)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper functions to create VM, InteropContext, TX, Account, Contract.
|
// Helper functions to create VM, InteropContext, TX, Account, Contract.
|
||||||
|
|
||||||
func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) {
|
func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) {
|
||||||
|
|
|
@ -529,25 +529,3 @@ func contractDestroy(ic *interop.Context, v *vm.VM) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// contractGetStorageContext retrieves StorageContext of a contract.
|
|
||||||
func contractGetStorageContext(ic *interop.Context, v *vm.VM) error {
|
|
||||||
csInterface := v.Estack().Pop().Value()
|
|
||||||
cs, ok := csInterface.(*state.Contract)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%T is not a contract state", cs)
|
|
||||||
}
|
|
||||||
_, err := ic.DAO.GetContractState(cs.ScriptHash())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("non-existent contract")
|
|
||||||
}
|
|
||||||
_, err = ic.LowerDAO.GetContractState(cs.ScriptHash())
|
|
||||||
if err == nil {
|
|
||||||
return fmt.Errorf("contract was not created in this transaction")
|
|
||||||
}
|
|
||||||
stc := &StorageContext{
|
|
||||||
ScriptHash: cs.ScriptHash(),
|
|
||||||
}
|
|
||||||
v.Estack().PushVal(stackitem.NewInterop(stc))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -70,8 +70,9 @@ var systemInterops = []interop.Function{
|
||||||
{Name: "System.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
|
{Name: "System.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
|
||||||
{Name: "System.Contract.Call", Func: contractCall, Price: 1},
|
{Name: "System.Contract.Call", Func: contractCall, Price: 1},
|
||||||
{Name: "System.Contract.CallEx", Func: contractCallEx, Price: 1},
|
{Name: "System.Contract.CallEx", Func: contractCallEx, Price: 1},
|
||||||
|
{Name: "System.Contract.Create", Func: contractCreate, Price: 0},
|
||||||
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1},
|
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1},
|
||||||
{Name: "System.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
{Name: "System.Contract.Update", Func: contractUpdate, Price: 0},
|
||||||
{Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 1},
|
{Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 1},
|
||||||
{Name: "System.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
{Name: "System.Enumerator.Create", Func: enumerator.Create, Price: 1},
|
||||||
{Name: "System.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
{Name: "System.Enumerator.Next", Func: enumerator.Next, Price: 1},
|
||||||
|
@ -104,12 +105,6 @@ var systemInterops = []interop.Function{
|
||||||
}
|
}
|
||||||
|
|
||||||
var neoInterops = []interop.Function{
|
var neoInterops = []interop.Function{
|
||||||
{Name: "Neo.Contract.Create", Func: contractCreate, Price: 0},
|
|
||||||
{Name: "Neo.Contract.Destroy", Func: contractDestroy, Price: 1},
|
|
||||||
{Name: "Neo.Contract.GetScript", Func: contractGetScript, Price: 1},
|
|
||||||
{Name: "Neo.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
|
|
||||||
{Name: "Neo.Contract.IsPayable", Func: contractIsPayable, Price: 1},
|
|
||||||
{Name: "Neo.Contract.Migrate", Func: contractMigrate, Price: 0},
|
|
||||||
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1},
|
{Name: "Neo.Crypto.ECDsaVerify", Func: crypto.ECDSAVerify, Price: 1},
|
||||||
{Name: "Neo.Crypto.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1},
|
{Name: "Neo.Crypto.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1},
|
||||||
{Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1},
|
{Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1},
|
||||||
|
|
|
@ -32,9 +32,6 @@ func TestUnexpectedNonInterops(t *testing.T) {
|
||||||
|
|
||||||
// All of these functions expect an interop item on the stack.
|
// All of these functions expect an interop item on the stack.
|
||||||
funcs := []func(*interop.Context, *vm.VM) error{
|
funcs := []func(*interop.Context, *vm.VM) error{
|
||||||
contractGetScript,
|
|
||||||
contractGetStorageContext,
|
|
||||||
contractIsPayable,
|
|
||||||
storageContextAsReadOnly,
|
storageContextAsReadOnly,
|
||||||
storageDelete,
|
storageDelete,
|
||||||
storageFind,
|
storageFind,
|
||||||
|
|
|
@ -3,54 +3,32 @@ Package contract provides functions to work with contracts.
|
||||||
*/
|
*/
|
||||||
package contract
|
package contract
|
||||||
|
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
|
||||||
|
|
||||||
// Contract represents a Neo contract and is used in interop functions. It's
|
// Contract represents a Neo contract and is used in interop functions. It's
|
||||||
// an opaque data structure that you can manipulate with using functions from
|
// an opaque data structure that you can manipulate with using functions from
|
||||||
// this package. It's similar in function to the Contract class in the Neo .net
|
// this package. It's similar in function to the Contract class in the Neo .net
|
||||||
// framework.
|
// framework.
|
||||||
type Contract struct{}
|
type Contract struct{}
|
||||||
|
|
||||||
// GetScript returns the script of the given contract. It uses
|
|
||||||
// `Neo.Contract.GetScript` syscall.
|
|
||||||
func GetScript(c Contract) []byte {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPayable returns whether the given contract is payable (able to accept
|
|
||||||
// asset transfers to its address). It uses `Neo.Contract.IsPayable` syscall.
|
|
||||||
func IsPayable(c Contract) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStorageContext returns storage context for the given contract. It only
|
|
||||||
// works for contracts created in this transaction (so you can't take a storage
|
|
||||||
// context for arbitrary contract). Refer to the `storage` package on how to
|
|
||||||
// use this context. This function uses `Neo.Contract.GetStorageContext` syscall.
|
|
||||||
func GetStorageContext(c Contract) storage.Context {
|
|
||||||
return storage.Context{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create creates a new contract using a set of input parameters:
|
// Create creates a new contract using a set of input parameters:
|
||||||
// script contract's bytecode (limited in length by 1M)
|
// script contract's bytecode (limited in length by 1M)
|
||||||
// manifest contract's manifest (limited in length by 2 KiB)
|
// manifest contract's manifest (limited in length by 2 KiB)
|
||||||
// It returns this new created Contract when successful (and fails transaction
|
// It returns this new created Contract when successful (and fails transaction
|
||||||
// if not). It uses `Neo.Contract.Create` syscall.
|
// if not). It uses `System.Contract.Create` syscall.
|
||||||
func Create(script []byte, manifest []byte) Contract {
|
func Create(script []byte, manifest []byte) Contract {
|
||||||
return Contract{}
|
return Contract{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate migrates calling contract (that is the one that calls Migrate) to
|
// Update updates script and manifest of the calling contract (that is the one that calls Update)
|
||||||
// the new contract. Its parameters have exactly the same semantics as for
|
// to the new ones. Its parameters have exactly the same semantics as for
|
||||||
// Create. The old contract will be deleted by this call, if it has any storage
|
// Create. The old contract will be deleted by this call, if it has any storage
|
||||||
// associated it will be migrated to the new contract. New contract is returned.
|
// associated it will be migrated to the new contract. New contract is returned.
|
||||||
// This function uses `Neo.Contract.Migrate` syscall.
|
// This function uses `System.Contract.Update` syscall.
|
||||||
func Migrate(script []byte, manifest []byte) Contract {
|
func Update(script []byte, manifest []byte) Contract {
|
||||||
return Contract{}
|
return Contract{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy deletes calling contract (the one that calls Destroy) from the
|
// Destroy deletes calling contract (the one that calls Destroy) from the
|
||||||
// blockchain, so it's only possible to do that from the contract itself and
|
// blockchain, so it's only possible to do that from the contract itself and
|
||||||
// not by any outside code. When contract is deleted all associated storage
|
// not by any outside code. When contract is deleted all associated storage
|
||||||
// items are deleted too. This function uses `Neo.Contract.Destroy` syscall.
|
// items are deleted too. This function uses `System.Contract.Destroy` syscall.
|
||||||
func Destroy() {}
|
func Destroy() {}
|
||||||
|
|
|
@ -24,7 +24,7 @@ func CreateDeploymentScript(avm []byte, manif *manifest.Manifest) ([]byte, util.
|
||||||
rawManifest := w.Bytes()
|
rawManifest := w.Bytes()
|
||||||
emit.Bytes(script.BinWriter, rawManifest)
|
emit.Bytes(script.BinWriter, rawManifest)
|
||||||
emit.Bytes(script.BinWriter, avm)
|
emit.Bytes(script.BinWriter, avm)
|
||||||
emit.Syscall(script.BinWriter, "Neo.Contract.Create")
|
emit.Syscall(script.BinWriter, "System.Contract.Create")
|
||||||
sysfee := util.Fixed8(core.StoragePrice * (len(avm) + len(rawManifest)))
|
sysfee := util.Fixed8(core.StoragePrice * (len(avm) + len(rawManifest)))
|
||||||
return script.Bytes(), sysfee, nil
|
return script.Bytes(), sysfee, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,12 +56,12 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"getapplicationlog": {
|
"getapplicationlog": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["9d84eee99b8fda7cba4931ae54b316c1c0468bd4526b8b4eb6cf62d771abe9c7"]`,
|
params: `["136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20"]`,
|
||||||
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
|
||||||
check: func(t *testing.T, e *executor, acc interface{}) {
|
check: func(t *testing.T, e *executor, acc interface{}) {
|
||||||
res, ok := acc.(*result.ApplicationLog)
|
res, ok := acc.(*result.ApplicationLog)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
expectedTxHash, err := util.Uint256DecodeStringLE("9d84eee99b8fda7cba4931ae54b316c1c0468bd4526b8b4eb6cf62d771abe9c7")
|
expectedTxHash, err := util.Uint256DecodeStringLE("136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedTxHash, res.TxHash)
|
assert.Equal(t, expectedTxHash, res.TxHash)
|
||||||
assert.Equal(t, 1, len(res.Executions))
|
assert.Equal(t, 1, len(res.Executions))
|
||||||
|
@ -483,7 +483,7 @@ var rpcTestCases = map[string][]rpcTestCase{
|
||||||
"gettransactionheight": {
|
"gettransactionheight": {
|
||||||
{
|
{
|
||||||
name: "positive",
|
name: "positive",
|
||||||
params: `["9d84eee99b8fda7cba4931ae54b316c1c0468bd4526b8b4eb6cf62d771abe9c7"]`,
|
params: `["136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20"]`,
|
||||||
result: func(e *executor) interface{} {
|
result: func(e *executor) interface{} {
|
||||||
h := 0
|
h := 0
|
||||||
return &h
|
return &h
|
||||||
|
|
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
BIN
pkg/rpc/server/testdata/testblocks.acc
vendored
Binary file not shown.
Loading…
Reference in a new issue