core: implement System.Contract.IsStandard syscall
This commit is contained in:
parent
b1d2d70c02
commit
5b4f38d717
3 changed files with 47 additions and 0 deletions
|
@ -470,3 +470,19 @@ func contractDestroy(ic *interop.Context, v *vm.VM) error {
|
||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"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/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -145,3 +149,29 @@ func TestBCGetBlock(t *testing.T) {
|
||||||
require.True(t, ok)
|
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())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -91,6 +91,7 @@ var systemInterops = []interop.Function{
|
||||||
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
|
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
|
||||||
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1000000,
|
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1000000,
|
||||||
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
|
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
|
||||||
|
{Name: "System.Contract.IsStandard", Func: contractIsStandard, Price: 30000},
|
||||||
{Name: "System.Contract.Update", Func: contractUpdate, Price: 0,
|
{Name: "System.Contract.Update", Func: contractUpdate, Price: 0,
|
||||||
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
|
AllowedTriggers: trigger.Application, RequiredFlags: smartcontract.AllowModifyStates},
|
||||||
{Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 400},
|
{Name: "System.Enumerator.Concat", Func: enumerator.Concat, Price: 400},
|
||||||
|
|
Loading…
Reference in a new issue