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:
Evgenii Stratonikov 2020-06-10 14:07:26 +03:00
parent c69f8a2fa3
commit f8a11f61b6
12 changed files with 18 additions and 119 deletions

View file

@ -37,12 +37,9 @@ var syscalls = map[string]map[string]string{
"GetTransactionHeight": "System.Blockchain.GetTransactionHeight",
},
"contract": {
"GetScript": "Neo.Contract.GetScript",
"IsPayable": "Neo.Contract.IsPayable",
"Create": "Neo.Contract.Create",
"Destroy": "Neo.Contract.Destroy",
"Migrate": "Neo.Contract.Migrate",
"GetStorageContext": "Neo.Contract.GetStorageContext",
"Create": "System.Contract.Create",
"Destroy": "System.Contract.Destroy",
"Update": "System.Contract.Update",
},
"engine": {
"GetScriptContainer": "System.ExecutionEngine.GetScriptContainer",

View file

@ -236,7 +236,7 @@ func TestCreateBasicChain(t *testing.T) {
require.NoError(t, err)
emit.Bytes(script.BinWriter, bs)
emit.Bytes(script.BinWriter, avm)
emit.Syscall(script.BinWriter, "Neo.Contract.Create")
emit.Syscall(script.BinWriter, "System.Contract.Create")
txScript := script.Bytes()
invFee := util.Fixed8FromFloat(100)

View file

@ -28,7 +28,6 @@ type Context struct {
Block *block.Block
Tx *transaction.Transaction
DAO *dao.Cached
LowerDAO dao.DAO
Notifications []state.NotificationEvent
Log *zap.Logger
}
@ -44,7 +43,6 @@ func NewContext(trigger trigger.Type, bc blockchainer.Blockchainer, d dao.DAO, n
Block: block,
Tx: tx,
DAO: dao,
LowerDAO: d,
Notifications: nes,
Log: log,
}

View file

@ -114,30 +114,8 @@ func contractCreate(ic *interop.Context, v *vm.VM) error {
return nil
}
// contractGetScript returns a script associated with a contract.
func contractGetScript(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 {
// contractUpdate migrates a contract.
func contractUpdate(ic *interop.Context, v *vm.VM) error {
contract, err := ic.DAO.GetContractState(v.GetCurrentScriptHash())
if contract == nil {
return errors.New("contract doesn't exist")

View file

@ -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.
func createVM(t *testing.T) (*vm.VM, *interop.Context, *Blockchain) {

View file

@ -529,25 +529,3 @@ func contractDestroy(ic *interop.Context, v *vm.VM) error {
}
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
}

View file

@ -70,8 +70,9 @@ var systemInterops = []interop.Function{
{Name: "System.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
{Name: "System.Contract.Call", Func: contractCall, 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.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.Create", Func: enumerator.Create, Price: 1},
{Name: "System.Enumerator.Next", Func: enumerator.Next, Price: 1},
@ -104,12 +105,6 @@ var systemInterops = []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.ECDsaCheckMultiSig", Func: crypto.ECDSACheckMultisig, Price: 1},
{Name: "Neo.Crypto.SHA256", Func: crypto.Sha256, Price: 1},

View file

@ -32,9 +32,6 @@ func TestUnexpectedNonInterops(t *testing.T) {
// All of these functions expect an interop item on the stack.
funcs := []func(*interop.Context, *vm.VM) error{
contractGetScript,
contractGetStorageContext,
contractIsPayable,
storageContextAsReadOnly,
storageDelete,
storageFind,

View file

@ -3,54 +3,32 @@ Package contract provides functions to work with contracts.
*/
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
// 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
// framework.
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:
// script contract's bytecode (limited in length by 1M)
// manifest contract's manifest (limited in length by 2 KiB)
// 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 {
return Contract{}
}
// Migrate migrates calling contract (that is the one that calls Migrate) to
// the new contract. Its parameters have exactly the same semantics as for
// Update updates script and manifest of the calling contract (that is the one that calls Update)
// 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
// associated it will be migrated to the new contract. New contract is returned.
// This function uses `Neo.Contract.Migrate` syscall.
func Migrate(script []byte, manifest []byte) Contract {
// This function uses `System.Contract.Update` syscall.
func Update(script []byte, manifest []byte) Contract {
return Contract{}
}
// 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
// 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() {}

View file

@ -24,7 +24,7 @@ func CreateDeploymentScript(avm []byte, manif *manifest.Manifest) ([]byte, util.
rawManifest := w.Bytes()
emit.Bytes(script.BinWriter, rawManifest)
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)))
return script.Bytes(), sysfee, nil
}

View file

@ -56,12 +56,12 @@ var rpcTestCases = map[string][]rpcTestCase{
"getapplicationlog": {
{
name: "positive",
params: `["9d84eee99b8fda7cba4931ae54b316c1c0468bd4526b8b4eb6cf62d771abe9c7"]`,
params: `["136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20"]`,
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
check: func(t *testing.T, e *executor, acc interface{}) {
res, ok := acc.(*result.ApplicationLog)
require.True(t, ok)
expectedTxHash, err := util.Uint256DecodeStringLE("9d84eee99b8fda7cba4931ae54b316c1c0468bd4526b8b4eb6cf62d771abe9c7")
expectedTxHash, err := util.Uint256DecodeStringLE("136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20")
require.NoError(t, err)
assert.Equal(t, expectedTxHash, res.TxHash)
assert.Equal(t, 1, len(res.Executions))
@ -483,7 +483,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"gettransactionheight": {
{
name: "positive",
params: `["9d84eee99b8fda7cba4931ae54b316c1c0468bd4526b8b4eb6cf62d771abe9c7"]`,
params: `["136ef2ba8259d121a173da2588ae0fbb735f0f740820fded9cd8da8fee109b20"]`,
result: func(e *executor) interface{} {
h := 0
return &h

Binary file not shown.