2020-03-19 15:52:37 +00:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
2020-05-07 11:11:59 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
2020-03-19 15:52:37 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
type testNative struct {
|
2020-04-22 20:00:18 +00:00
|
|
|
meta interop.ContractMD
|
2020-03-19 15:52:37 +00:00
|
|
|
blocks chan uint32
|
|
|
|
}
|
|
|
|
|
2020-04-22 20:00:18 +00:00
|
|
|
func (tn *testNative) Initialize(_ *interop.Context) error {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tn *testNative) Metadata() *interop.ContractMD {
|
2020-03-19 15:52:37 +00:00
|
|
|
return &tn.meta
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tn *testNative) OnPersist(ic *interop.Context) error {
|
|
|
|
select {
|
|
|
|
case tn.blocks <- ic.Block.Index:
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return errors.New("error on persist")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-22 20:00:18 +00:00
|
|
|
var _ interop.Contract = (*testNative)(nil)
|
|
|
|
|
|
|
|
// registerNative registers native contract in the blockchain.
|
|
|
|
func (bc *Blockchain) registerNative(c interop.Contract) {
|
|
|
|
bc.contracts.Contracts = append(bc.contracts.Contracts, c)
|
|
|
|
}
|
2020-03-19 15:52:37 +00:00
|
|
|
|
|
|
|
func newTestNative() *testNative {
|
|
|
|
tn := &testNative{
|
2020-04-22 20:00:18 +00:00
|
|
|
meta: *interop.NewContractMD("Test.Native.Sum"),
|
2020-03-19 15:52:37 +00:00
|
|
|
blocks: make(chan uint32, 1),
|
|
|
|
}
|
|
|
|
desc := &manifest.Method{
|
|
|
|
Name: "sum",
|
|
|
|
Parameters: []manifest.Parameter{
|
|
|
|
manifest.NewParameter("addend1", smartcontract.IntegerType),
|
|
|
|
manifest.NewParameter("addend2", smartcontract.IntegerType),
|
|
|
|
},
|
|
|
|
ReturnType: smartcontract.IntegerType,
|
|
|
|
}
|
2020-04-22 20:00:18 +00:00
|
|
|
md := &interop.MethodAndPrice{
|
2020-03-19 15:52:37 +00:00
|
|
|
Func: tn.sum,
|
|
|
|
Price: 1,
|
|
|
|
RequiredFlags: smartcontract.NoneFlag,
|
|
|
|
}
|
|
|
|
tn.meta.AddMethod(md, desc, true)
|
|
|
|
|
|
|
|
return tn
|
|
|
|
}
|
|
|
|
|
|
|
|
func (tn *testNative) sum(_ *interop.Context, args []vm.StackItem) vm.StackItem {
|
|
|
|
s1, err := args[0].TryInteger()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
s2, err := args[1].TryInteger()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return vm.NewBigIntegerItem(s1.Add(s1, s2))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNativeContract_Invoke(t *testing.T) {
|
|
|
|
chain := newTestChain(t)
|
|
|
|
defer chain.Close()
|
|
|
|
|
|
|
|
tn := newTestNative()
|
2020-04-22 20:00:18 +00:00
|
|
|
chain.registerNative(tn)
|
2020-03-19 15:52:37 +00:00
|
|
|
|
2020-05-07 11:11:59 +00:00
|
|
|
err := chain.dao.PutContractState(&state.Contract{Script: tn.meta.Script})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-03-19 15:52:37 +00:00
|
|
|
w := io.NewBufBinWriter()
|
|
|
|
emit.AppCallWithOperationAndArgs(w.BinWriter, tn.Metadata().Hash, "sum", int64(14), int64(28))
|
|
|
|
script := w.Bytes()
|
2020-06-05 13:07:04 +00:00
|
|
|
tx := transaction.New(script, 0)
|
2020-03-19 15:52:37 +00:00
|
|
|
validUntil := chain.blockHeight + 1
|
|
|
|
tx.ValidUntilBlock = validUntil
|
2020-04-22 17:42:38 +00:00
|
|
|
require.NoError(t, addSender(tx))
|
|
|
|
require.NoError(t, signTx(chain, tx))
|
|
|
|
b := chain.newBlock(tx)
|
2020-03-19 15:52:37 +00:00
|
|
|
require.NoError(t, chain.AddBlock(b))
|
|
|
|
|
|
|
|
res, err := chain.GetAppExecResult(tx.Hash())
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, "HALT", res.VMState)
|
|
|
|
require.Equal(t, 1, len(res.Stack))
|
|
|
|
require.Equal(t, smartcontract.IntegerType, res.Stack[0].Type)
|
|
|
|
require.EqualValues(t, 42, res.Stack[0].Value)
|
|
|
|
|
|
|
|
require.NoError(t, chain.persist())
|
|
|
|
select {
|
|
|
|
case index := <-tn.blocks:
|
|
|
|
require.Equal(t, chain.blockHeight, index)
|
|
|
|
default:
|
|
|
|
require.Fail(t, "onPersist wasn't called")
|
|
|
|
}
|
|
|
|
}
|