core: implement System.Contract.IsStandard syscall

This commit is contained in:
Evgenii Stratonikov 2020-06-16 11:17:18 +03:00
parent b1d2d70c02
commit 5b4f38d717
3 changed files with 47 additions and 0 deletions

View file

@ -470,3 +470,19 @@ func contractDestroy(ic *interop.Context, v *vm.VM) error {
}
return nil
}
// contractIsStandard checks if contract is standard (sig or multisig) contract.
func contractIsStandard(ic *interop.Context, v *vm.VM) error {
h := v.Estack().Pop().Bytes()
u, err := util.Uint160DecodeBytesBE(h)
if err != nil {
return err
}
var result bool
cs, _ := ic.DAO.GetContractState(u)
if cs == nil || vm.IsStandardContract(cs.Script) {
result = true
}
v.Estack().PushVal(result)
return nil
}

View file

@ -4,6 +4,10 @@ import (
"math/big"
"testing"
"github.com/nspcc-dev/dbft/crypto"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/stretchr/testify/require"
)
@ -145,3 +149,29 @@ func TestBCGetBlock(t *testing.T) {
require.True(t, ok)
})
}
func TestContractIsStandard(t *testing.T) {
v, ic, chain := createVM(t)
defer chain.Close()
t.Run("True", func(t *testing.T) {
priv, err := keys.NewPrivateKey()
require.NoError(t, err)
pub := priv.PublicKey()
err = ic.DAO.PutContractState(&state.Contract{ID: 42, Script: pub.GetVerificationScript()})
require.NoError(t, err)
v.Estack().PushVal(pub.GetScriptHash().BytesBE())
require.NoError(t, contractIsStandard(ic, v))
require.True(t, v.Estack().Pop().Bool())
})
t.Run("False", func(t *testing.T) {
script := []byte{byte(opcode.PUSHT)}
require.NoError(t, ic.DAO.PutContractState(&state.Contract{ID: 24, Script: script}))
v.Estack().PushVal(crypto.Hash160(script).BytesBE())
require.NoError(t, contractIsStandard(ic, v))
require.False(t, v.Estack().Pop().Bool())
})
}

View file

@ -91,6 +91,7 @@ var systemInterops = []interop.Function{
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1000000,
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
{Name: "System.Contract.IsStandard", Func: contractIsStandard, Price: 30000},
{Name: "System.Contract.Update", Func: contractUpdate, Price: 0,
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
{Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 400},