diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index fc82226cb..f8798f164 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -279,6 +279,7 @@ func TestCreateBasicChain(t *testing.T) { // Push some contract into the chain. avm, err := ioutil.ReadFile(prefix + "test_contract.avm") require.NoError(t, err) + t.Logf("contractHash: %s", hash.Hash160(avm).StringLE()) var props smartcontract.PropertyState script := io.NewBufBinWriter() @@ -352,6 +353,22 @@ func TestCreateBasicChain(t *testing.T) { b = bc.newBlock(newMinerTX(), txNeo0to1) require.NoError(t, bc.AddBlock(b)) + sh := hash.Hash160(avm) + w := io.NewBufBinWriter() + emit.Int(w.BinWriter, 0) + emit.Opcode(w.BinWriter, opcode.NEWARRAY) + emit.String(w.BinWriter, "init") + emit.AppCall(w.BinWriter, sh, true) + initTx := transaction.NewInvocationTX(w.Bytes(), 0) + transferTx := newNEP5Transfer(sh, sh, priv0.GetScriptHash(), 1000) + + b = bc.newBlock(newMinerTX(), initTx, transferTx) + require.NoError(t, bc.AddBlock(b)) + + transferTx = newNEP5Transfer(sh, priv0.GetScriptHash(), priv1.GetScriptHash(), 123) + b = bc.newBlock(newMinerTX(), transferTx) + require.NoError(t, bc.AddBlock(b)) + if saveChain { outStream, err := os.Create(prefix + "testblocks.acc") require.NoError(t, err) @@ -375,3 +392,18 @@ func TestCreateBasicChain(t *testing.T) { } } } + +func newNEP5Transfer(sc, from, to util.Uint160, amount int64) *transaction.Transaction { + w := io.NewBufBinWriter() + emit.Int(w.BinWriter, amount) + emit.Bytes(w.BinWriter, to.BytesBE()) + emit.Bytes(w.BinWriter, from.BytesBE()) + emit.Int(w.BinWriter, 3) + emit.Opcode(w.BinWriter, opcode.PACK) + emit.String(w.BinWriter, "transfer") + emit.AppCall(w.BinWriter, sc, false) + emit.Opcode(w.BinWriter, opcode.THROWIFNOT) + + script := w.Bytes() + return transaction.NewInvocationTX(script, 0) +} diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index fb39e0fcf..ada0a8623 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -44,14 +44,14 @@ var rpcTestCases = map[string][]rpcTestCase{ "getapplicationlog": { { name: "positive", - params: `["2441c2776cbab65bf81d38a839cf3a85689421631d4ba091be64703f02867315"]`, + params: `["440b84d1580e36e84379416b58d9a3ad978cc557e54fd7ec6a2648329975b333"]`, 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("2441c2776cbab65bf81d38a839cf3a85689421631d4ba091be64703f02867315") + expectedTxHash, err := util.Uint256DecodeStringLE("cdb9fef85da4efde173682233b1a6166c9f39e8e41e40b75abb88230bf0c04bc") require.NoError(t, err) assert.Equal(t, expectedTxHash, res.TxHash) assert.Equal(t, 1, len(res.Executions)) @@ -117,13 +117,13 @@ var rpcTestCases = map[string][]rpcTestCase{ "getcontractstate": { { name: "positive", - params: `["1a696b32e239dd5eace3f025cac0a193a5746a27"]`, + params: `["d864728bdbc88da799bc43862ae6aaa62adc3a87"]`, result: func(e *executor) interface{} { return &result.ContractState{} }, check: func(t *testing.T, e *executor, cs interface{}) { res, ok := cs.(*result.ContractState) require.True(t, ok) assert.Equal(t, byte(0), res.Version) - assert.Equal(t, util.Uint160{0x1a, 0x69, 0x6b, 0x32, 0xe2, 0x39, 0xdd, 0x5e, 0xac, 0xe3, 0xf0, 0x25, 0xca, 0xc0, 0xa1, 0x93, 0xa5, 0x74, 0x6a, 0x27}, res.ScriptHash) + assert.Equal(t, util.Uint160{0xd8, 0x64, 0x72, 0x8b, 0xdb, 0xc8, 0x8d, 0xa7, 0x99, 0xbc, 0x43, 0x86, 0x2a, 0xe6, 0xaa, 0xa6, 0x2a, 0xdc, 0x3a, 0x87}, res.ScriptHash) assert.Equal(t, "0.99", res.CodeVersion) }, }, @@ -146,7 +146,7 @@ var rpcTestCases = map[string][]rpcTestCase{ "getstorage": { { name: "positive", - params: `["1a696b32e239dd5eace3f025cac0a193a5746a27", "746573746b6579"]`, + params: `["d864728bdbc88da799bc43862ae6aaa62adc3a87", "746573746b6579"]`, result: func(e *executor) interface{} { v := hex.EncodeToString([]byte("testvalue")) return &v @@ -154,7 +154,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "missing key", - params: `["1a696b32e239dd5eace3f025cac0a193a5746a27", "7465"]`, + params: `["d864728bdbc88da799bc43862ae6aaa62adc3a87", "7465"]`, result: func(e *executor) interface{} { v := "" return &v @@ -167,7 +167,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "no second parameter", - params: `["1a696b32e239dd5eace3f025cac0a193a5746a27"]`, + params: `["d864728bdbc88da799bc43862ae6aaa62adc3a87"]`, fail: true, }, { @@ -177,7 +177,7 @@ var rpcTestCases = map[string][]rpcTestCase{ }, { name: "invalid key", - params: `["1a696b32e239dd5eace3f025cac0a193a5746a27", "notahex"]`, + params: `["d864728bdbc88da799bc43862ae6aaa62adc3a87", "notahex"]`, fail: true, }, }, diff --git a/pkg/rpc/server/testdata/test_contract.avm b/pkg/rpc/server/testdata/test_contract.avm index 15e36929d..7d3417c3c 100755 Binary files a/pkg/rpc/server/testdata/test_contract.avm and b/pkg/rpc/server/testdata/test_contract.avm differ diff --git a/pkg/rpc/server/testdata/test_contract.go b/pkg/rpc/server/testdata/test_contract.go index 33b4d5bd3..a8da7cf8a 100644 --- a/pkg/rpc/server/testdata/test_contract.go +++ b/pkg/rpc/server/testdata/test_contract.go @@ -1,9 +1,82 @@ package testdata -import "github.com/nspcc-dev/neo-go/pkg/interop/storage" +import ( + "github.com/nspcc-dev/neo-go/pkg/interop/engine" + "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + "github.com/nspcc-dev/neo-go/pkg/interop/storage" +) + +const ( + totalSupply = 1000000 + decimals = 2 +) func Main(operation string, args []interface{}) interface{} { - ctx := storage.GetContext() - storage.Put(ctx, args[0].([]byte), args[1].([]byte)) - return true + runtime.Notify([]interface{}{"contract call", operation, args}) + switch operation { + case "Put": + ctx := storage.GetContext() + storage.Put(ctx, args[0].([]byte), args[1].([]byte)) + return true + case "totalSupply": + return totalSupply + case "decimals": + return decimals + case "name": + return "Rubl" + case "symbol": + return "RUB" + case "balanceOf": + ctx := storage.GetContext() + addr := args[0].([]byte) + if len(addr) != 20 { + runtime.Log("invalid address") + return false + } + amount := storage.Get(ctx, addr).(int) + runtime.Notify([]interface{}{"balanceOf", addr, amount}) + return amount + case "transfer": + ctx := storage.GetContext() + from := args[0].([]byte) + if len(from) != 20 { + runtime.Log("invalid 'from' address") + return false + } + to := args[1].([]byte) + if len(to) != 20 { + runtime.Log("invalid 'to' address") + return false + } + amount := args[2].(int) + if amount < 0 { + runtime.Log("invalid amount") + return false + } + + fromBalance := storage.Get(ctx, from).(int) + if fromBalance < amount { + runtime.Log("insufficient funds") + return false + } + fromBalance -= amount + storage.Put(ctx, from, fromBalance) + + toBalance := storage.Get(ctx, to).(int) + toBalance += amount + storage.Put(ctx, to, toBalance) + + runtime.Notify([]interface{}{"transfer", from, to, amount}) + + return true + case "init": + ctx := storage.GetContext() + h := engine.GetExecutingScriptHash() + amount := totalSupply + storage.Put(ctx, h, amount) + runtime.Notify([]interface{}{"transfer", []byte{}, h, amount}) + return true + default: + panic("invalid operation") + } } diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index 5507af4ea..af3c153a0 100644 Binary files a/pkg/rpc/server/testdata/testblocks.acc and b/pkg/rpc/server/testdata/testblocks.acc differ