From a237e34c1f75da2b6f8e4c3f81718fbb72df5bf1 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Tue, 9 Feb 2021 12:05:45 +0300 Subject: [PATCH] rpc: add test for `submitNotaryRequest` --- pkg/core/helper_test.go | 29 +++++ pkg/network/server_test.go | 1 - pkg/rpc/server/client_test.go | 107 ++++++++++++++++ pkg/rpc/server/server_helper_test.go | 35 ++++- pkg/rpc/server/server_test.go | 170 +++++++++++++++++++++++-- pkg/rpc/server/testdata/testblocks.acc | Bin 7675 -> 9869 bytes 6 files changed, 325 insertions(+), 17 deletions(-) diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index 342678823..733ecf969 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "math/big" "os" + "path" "strings" "testing" "time" @@ -25,6 +26,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" + "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" @@ -296,9 +298,11 @@ func initBasicChain(t *testing.T, bc *Blockchain) { gasHash := bc.contracts.GAS.Hash neoHash := bc.contracts.NEO.Hash policyHash := bc.contracts.Policy.Hash + notaryHash := bc.contracts.Notary.Hash t.Logf("native GAS hash: %v", gasHash) t.Logf("native NEO hash: %v", neoHash) t.Logf("native Policy hash: %v", policyHash) + t.Logf("native Notary hash: %v", notaryHash) priv0 := testchain.PrivateKeyByID(0) priv0ScriptHash := priv0.GetScriptHash() @@ -426,6 +430,31 @@ func initBasicChain(t *testing.T, bc *Blockchain) { require.NoError(t, acc0.SignTx(txDeploy2)) b = bc.newBlock(txDeploy2) require.NoError(t, bc.AddBlock(b)) + + // Deposit some GAS to notary contract for priv0 + transferTx = newNEP17Transfer(gasHash, priv0.GetScriptHash(), notaryHash, 10_0000_0000, priv0.GetScriptHash(), int64(bc.BlockHeight()+1000)) + transferTx.Nonce = getNextNonce() + transferTx.ValidUntilBlock = validUntilBlock + transferTx.Signers = []transaction.Signer{ + { + Account: priv0ScriptHash, + Scopes: transaction.CalledByEntry, + }, + } + require.NoError(t, addNetworkFee(bc, transferTx, acc0)) + transferTx.SystemFee += 10_0000 + require.NoError(t, acc0.SignTx(transferTx)) + + b = bc.newBlock(transferTx) + require.NoError(t, bc.AddBlock(b)) + t.Logf("notaryDepositTxPriv0: %v", transferTx.Hash().StringLE()) + + // Designate new Notary node + ntr, err := wallet.NewWalletFromFile(path.Join(notaryModulePath, "./testdata/notary1.json")) + require.NoError(t, err) + require.NoError(t, ntr.Accounts[0].Decrypt("one")) + bc.setNodesByRole(t, true, native.RoleP2PNotary, keys.PublicKeys{ntr.Accounts[0].PrivateKey().PublicKey()}) + t.Logf("Designated Notary node: %s", hex.EncodeToString(ntr.Accounts[0].PrivateKey().PublicKey().Bytes())) } func newNEP17Transfer(sc, from, to util.Uint160, amount int64, additionalArgs ...interface{}) *transaction.Transaction { diff --git a/pkg/network/server_test.go b/pkg/network/server_test.go index 85fd51c36..3e3e79292 100644 --- a/pkg/network/server_test.go +++ b/pkg/network/server_test.go @@ -22,7 +22,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/atomic" diff --git a/pkg/rpc/server/client_test.go b/pkg/rpc/server/client_test.go index c7980e571..acca59101 100644 --- a/pkg/rpc/server/client_test.go +++ b/pkg/rpc/server/client_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/nspcc-dev/neo-go/internal/testchain" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core/fee" "github.com/nspcc-dev/neo-go/pkg/core/native/nativenames" "github.com/nspcc-dev/neo-go/pkg/core/transaction" @@ -17,6 +18,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" "github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/stretchr/testify/require" @@ -214,6 +216,111 @@ func TestSignAndPushInvocationTx(t *testing.T) { require.EqualValues(t, 30, tx.SystemFee) } +func TestSignAndPushP2PNotaryRequest(t *testing.T) { + chain, rpcSrv, httpSrv := initServerWithInMemoryChainAndServices(t, false, true) + defer chain.Close() + defer rpcSrv.Shutdown() + + c, err := client.New(context.Background(), httpSrv.URL, client.Options{}) + require.NoError(t, err) + + t.Run("client wasn't initialized", func(t *testing.T) { + _, err := c.SignAndPushP2PNotaryRequest(nil, nil, 0, 0, 0, nil) + require.NotNil(t, err) + }) + + require.NoError(t, c.Init()) + t.Run("bad account address", func(t *testing.T) { + _, err := c.SignAndPushP2PNotaryRequest(nil, nil, 0, 0, 0, &wallet.Account{Address: "not-an-addr"}) + require.NotNil(t, err) + }) + + acc, err := wallet.NewAccount() + require.NoError(t, err) + t.Run("bad fallback script", func(t *testing.T) { + _, err := c.SignAndPushP2PNotaryRequest(nil, []byte{byte(opcode.ASSERT)}, -1, 0, 0, acc) + require.NotNil(t, err) + }) + + t.Run("too large fallbackValidFor", func(t *testing.T) { + _, err := c.SignAndPushP2PNotaryRequest(nil, []byte{byte(opcode.RET)}, -1, 0, 141, acc) + require.NotNil(t, err) + }) + + t.Run("good", func(t *testing.T) { + sender := testchain.PrivateKeyByID(0) // owner of the deposit in testchain + acc := wallet.NewAccountFromPrivateKey(sender) + expected := transaction.Transaction{ + Network: netmode.UnitTestNet, + Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, + Script: []byte{byte(opcode.RET)}, + ValidUntilBlock: chain.BlockHeight() + 5, + Signers: []transaction.Signer{{Account: util.Uint160{1, 5, 9}}}, + Scripts: []transaction.Witness{{ + InvocationScript: []byte{1, 4, 7}, + VerificationScript: []byte{3, 6, 9}, + }}, + } + mainTx := expected + _ = expected.Hash() + req, err := c.SignAndPushP2PNotaryRequest(&mainTx, []byte{byte(opcode.RET)}, -1, 0, 6, acc) + require.NoError(t, err) + + // check that request was correctly completed + require.Equal(t, expected, *req.MainTransaction) // main tx should be the same + require.ElementsMatch(t, []transaction.Attribute{ + { + Type: transaction.NotaryAssistedT, + Value: &transaction.NotaryAssisted{NKeys: 0}, + }, + { + Type: transaction.NotValidBeforeT, + Value: &transaction.NotValidBefore{Height: chain.BlockHeight()}, + }, + { + Type: transaction.ConflictsT, + Value: &transaction.Conflicts{Hash: mainTx.Hash()}, + }, + }, req.FallbackTransaction.Attributes) + require.Equal(t, []transaction.Signer{ + {Account: chain.GetNotaryContractScriptHash()}, + {Account: acc.PrivateKey().GetScriptHash()}, + }, req.FallbackTransaction.Signers) + + // it shouldn't be an error to add completed fallback to the chain + w, err := wallet.NewWalletFromFile(notaryPath) + require.NoError(t, err) + ntr := w.Accounts[0] + ntr.Decrypt(notaryPass) + req.FallbackTransaction.Scripts[0] = transaction.Witness{ + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, ntr.PrivateKey().Sign(req.FallbackTransaction.GetSignedPart())...), + VerificationScript: []byte{}, + } + b := testchain.NewBlock(t, chain, 1, 0, req.FallbackTransaction) + require.NoError(t, chain.AddBlock(b)) + appLogs, err := chain.GetAppExecResults(req.FallbackTransaction.Hash(), trigger.Application) + require.NoError(t, err) + require.Equal(t, 1, len(appLogs)) + appLog := appLogs[0] + require.Equal(t, vm.HaltState, appLog.VMState) + require.Equal(t, appLog.GasConsumed, req.FallbackTransaction.SystemFee) + }) +} + +func TestCalculateNotaryFee(t *testing.T) { + chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) + defer chain.Close() + defer rpcSrv.Shutdown() + + c, err := client.New(context.Background(), httpSrv.URL, client.Options{}) + require.NoError(t, err) + + t.Run("client not initialized", func(t *testing.T) { + _, err := c.CalculateNotaryFee(0) + require.NotNil(t, err) + }) +} + func TestPing(t *testing.T) { chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t) defer chain.Close() diff --git a/pkg/rpc/server/server_helper_test.go b/pkg/rpc/server/server_helper_test.go index 3511ac5c2..aacb7961e 100644 --- a/pkg/rpc/server/server_helper_test.go +++ b/pkg/rpc/server/server_helper_test.go @@ -23,7 +23,12 @@ import ( "go.uber.org/zap/zaptest" ) -func getUnitTestChain(t *testing.T, enableOracle bool) (*core.Blockchain, *oracle.Oracle, config.Config, *zap.Logger) { +const ( + notaryPath = "../../services/notary/testdata/notary1.json" + notaryPass = "one" +) + +func getUnitTestChain(t *testing.T, enableOracle bool, enableNotary bool) (*core.Blockchain, *oracle.Oracle, config.Config, *zap.Logger) { net := netmode.UnitTestNet configPath := "../../../config" cfg, err := config.Load(configPath, net) @@ -31,6 +36,19 @@ func getUnitTestChain(t *testing.T, enableOracle bool) (*core.Blockchain, *oracl memoryStore := storage.NewMemoryStore() logger := zaptest.NewLogger(t) + if enableNotary { + cfg.ProtocolConfiguration.P2PSigExtensions = true + cfg.ProtocolConfiguration.P2PNotaryRequestPayloadPoolSize = 1000 + cfg.ProtocolConfiguration.P2PNotary = config.P2PNotary{ + Enabled: true, + UnlockWallet: config.Wallet{ + Path: notaryPath, + Password: notaryPass, + }, + } + } else { + cfg.ProtocolConfiguration.P2PNotary.Enabled = false + } chain, err := core.NewBlockchain(memoryStore, cfg.ProtocolConfiguration, logger) require.NoError(t, err, "could not create chain") @@ -79,8 +97,8 @@ func getTestBlocks(t *testing.T) []*block.Block { return blocks } -func initClearServerWithOracle(t *testing.T, needOracle bool) (*core.Blockchain, *Server, *httptest.Server) { - chain, orc, cfg, logger := getUnitTestChain(t, needOracle) +func initClearServerWithServices(t *testing.T, needOracle bool, needNotary bool) (*core.Blockchain, *Server, *httptest.Server) { + chain, orc, cfg, logger := getUnitTestChain(t, needOracle, needNotary) serverConfig := network.NewServerConfig(cfg) server, err := network.NewServer(serverConfig, chain, logger) @@ -96,7 +114,7 @@ func initClearServerWithOracle(t *testing.T, needOracle bool) (*core.Blockchain, } func initClearServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *httptest.Server) { - return initClearServerWithOracle(t, false) + return initClearServerWithServices(t, false, false) } func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *httptest.Server) { @@ -108,6 +126,15 @@ func initServerWithInMemoryChain(t *testing.T) (*core.Blockchain, *Server, *http return chain, rpcServer, srv } +func initServerWithInMemoryChainAndServices(t *testing.T, needOracle bool, needNotary bool) (*core.Blockchain, *Server, *httptest.Server) { + chain, rpcServer, srv := initClearServerWithServices(t, needOracle, needNotary) + + for _, b := range getTestBlocks(t) { + require.NoError(t, chain.AddBlock(b)) + } + return chain, rpcServer, srv +} + type FeerStub struct{} func (fs *FeerStub) FeePerByte() int64 { diff --git a/pkg/rpc/server/server_test.go b/pkg/rpc/server/server_test.go index fc68ae6e3..fbeebd2a2 100644 --- a/pkg/rpc/server/server_test.go +++ b/pkg/rpc/server/server_test.go @@ -19,6 +19,7 @@ import ( "github.com/gorilla/websocket" "github.com/nspcc-dev/neo-go/internal/testchain" "github.com/nspcc-dev/neo-go/internal/testserdes" + "github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/core" "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/fee" @@ -27,6 +28,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/io" + "github.com/nspcc-dev/neo-go/pkg/network/payload" "github.com/nspcc-dev/neo-go/pkg/rpc/response" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" rpc2 "github.com/nspcc-dev/neo-go/pkg/services/oracle/broadcaster" @@ -58,7 +60,7 @@ type rpcTestCase struct { } const testContractHash = "c6436aab21ebd15279b85af8d7b5808d38455b0a" -const deploymentTxHash = "9a9d6b0876d1e6cfd68efadd0facaaba7e07efbe7b24282d094a0893645581f3" +const deploymentTxHash = "d0de42d5d23211174a50d74fbd4a919631236a63f16431a5a7e7126759e7ba23" const genesisBlockHash = "0542f4350c6e236d0509bcd98188b0034bfbecc1a0c7fcdb8e4295310d468b70" const verifyContractHash = "03ffc0897543b9b709e0f8cab4a7682dae0ba943" @@ -649,7 +651,7 @@ var rpcTestCases = map[string][]rpcTestCase{ require.True(t, ok) expected := result.UnclaimedGas{ Address: testchain.MultisigScriptHash(), - Unclaimed: *big.NewInt(3500), + Unclaimed: *big.NewInt(4500), } assert.Equal(t, expected, *actual) }, @@ -918,6 +920,13 @@ var rpcTestCases = map[string][]rpcTestCase{ fail: true, }, }, + "submitnotaryrequest": { + { + name: "no params", + params: `[]`, + fail: true, + }, + }, "validateaddress": { { name: "positive", @@ -954,7 +963,7 @@ func TestRPC(t *testing.T) { } func TestSubmitOracle(t *testing.T) { - chain, rpcSrv, httpSrv := initClearServerWithOracle(t, true) + chain, rpcSrv, httpSrv := initClearServerWithServices(t, true, false) defer chain.Close() defer rpcSrv.Shutdown() @@ -986,6 +995,121 @@ func TestSubmitOracle(t *testing.T) { t.Run("Valid", runCase(t, false, pubStr, `1`, txSigStr, msgSigStr)) } +func TestSubmitNotaryRequest(t *testing.T) { + rpc := `{"jsonrpc": "2.0", "id": 1, "method": "submitnotaryrequest", "params": %s}` + + t.Run("disabled P2PSigExtensions", func(t *testing.T) { + chain, rpcSrv, httpSrv := initClearServerWithServices(t, false, false) + defer chain.Close() + defer rpcSrv.Shutdown() + req := fmt.Sprintf(rpc, "[]") + body := doRPCCallOverHTTP(req, httpSrv.URL, t) + checkErrGetResult(t, body, true) + }) + + chain, rpcSrv, httpSrv := initServerWithInMemoryChainAndServices(t, false, true) + defer chain.Close() + defer rpcSrv.Shutdown() + + runCase := func(t *testing.T, fail bool, params ...string) func(t *testing.T) { + return func(t *testing.T) { + ps := `[` + strings.Join(params, ",") + `]` + req := fmt.Sprintf(rpc, ps) + body := doRPCCallOverHTTP(req, httpSrv.URL, t) + checkErrGetResult(t, body, fail) + } + } + t.Run("missing request", runCase(t, true)) + t.Run("not a base64", runCase(t, true, `"not-a-base64$"`)) + t.Run("invalid request bytes", runCase(t, true, `"not-a-request"`)) + t.Run("invalid request", func(t *testing.T) { + mainTx := &transaction.Transaction{ + Network: netmode.UnitTestNet, + Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, + Script: []byte{byte(opcode.RET)}, + ValidUntilBlock: 123, + Signers: []transaction.Signer{{Account: util.Uint160{1, 5, 9}}}, + Scripts: []transaction.Witness{{ + InvocationScript: []byte{1, 4, 7}, + VerificationScript: []byte{3, 6, 9}, + }}, + } + fallbackTx := &transaction.Transaction{ + Network: netmode.UnitTestNet, + Script: []byte{byte(opcode.RET)}, + ValidUntilBlock: 123, + Attributes: []transaction.Attribute{ + {Type: transaction.NotValidBeforeT, Value: &transaction.NotValidBefore{Height: 123}}, + {Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: mainTx.Hash()}}, + {Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 0}}, + }, + Signers: []transaction.Signer{{Account: util.Uint160{1, 4, 7}}, {Account: util.Uint160{9, 8, 7}}}, + Scripts: []transaction.Witness{ + {InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, make([]byte, 64, 64)...), VerificationScript: make([]byte, 0)}, + {InvocationScript: []byte{1, 2, 3}, VerificationScript: []byte{1, 2, 3}}}, + } + p := &payload.P2PNotaryRequest{ + Network: netmode.UnitTestNet, + MainTransaction: mainTx, + FallbackTransaction: fallbackTx, + Witness: transaction.Witness{ + InvocationScript: []byte{1, 2, 3}, + VerificationScript: []byte{7, 8, 9}, + }, + } + bytes, err := p.Bytes() + require.NoError(t, err) + str := fmt.Sprintf(`"%s"`, base64.StdEncoding.EncodeToString(bytes)) + runCase(t, true, str)(t) + }) + t.Run("valid request", func(t *testing.T) { + sender := testchain.PrivateKeyByID(0) // owner of the deposit in testchain + mainTx := &transaction.Transaction{ + Network: netmode.UnitTestNet, + Attributes: []transaction.Attribute{{Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 1}}}, + Script: []byte{byte(opcode.RET)}, + ValidUntilBlock: 123, + Signers: []transaction.Signer{{Account: util.Uint160{1, 5, 9}}}, + Scripts: []transaction.Witness{{ + InvocationScript: []byte{1, 4, 7}, + VerificationScript: []byte{3, 6, 9}, + }}, + } + fallbackTx := &transaction.Transaction{ + Network: netmode.UnitTestNet, + Script: []byte{byte(opcode.RET)}, + ValidUntilBlock: 123, + Attributes: []transaction.Attribute{ + {Type: transaction.NotValidBeforeT, Value: &transaction.NotValidBefore{Height: 123}}, + {Type: transaction.ConflictsT, Value: &transaction.Conflicts{Hash: mainTx.Hash()}}, + {Type: transaction.NotaryAssistedT, Value: &transaction.NotaryAssisted{NKeys: 0}}, + }, + Signers: []transaction.Signer{{Account: chain.GetNotaryContractScriptHash()}, {Account: sender.GetScriptHash()}}, + Scripts: []transaction.Witness{ + {InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, make([]byte, 64, 64)...), VerificationScript: []byte{}}, + }, + NetworkFee: 2_0000_0000, + } + fallbackTx.Scripts = append(fallbackTx.Scripts, transaction.Witness{ + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, sender.Sign(fallbackTx.GetSignedPart())...), + VerificationScript: sender.PublicKey().GetVerificationScript(), + }) + p := &payload.P2PNotaryRequest{ + Network: netmode.UnitTestNet, + MainTransaction: mainTx, + FallbackTransaction: fallbackTx, + } + p.Witness = transaction.Witness{ + InvocationScript: append([]byte{byte(opcode.PUSHDATA1), 64}, sender.Sign(p.GetSignedPart())...), + VerificationScript: sender.PublicKey().GetVerificationScript(), + } + bytes, err := p.Bytes() + require.NoError(t, err) + str := fmt.Sprintf(`"%s"`, base64.StdEncoding.EncodeToString(bytes)) + runCase(t, false, str)(t) + }) +} + // testRPCProtocol runs a full set of tests using given callback to make actual // calls. Some tests change the chain state, thus we reinitialize the chain from // scratch here. @@ -1246,7 +1370,7 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] require.NoErrorf(t, err, "could not parse response: %s", txOut) assert.Equal(t, *block.Transactions[0], actual.Transaction) - assert.Equal(t, 8, actual.Confirmations) + assert.Equal(t, 10, actual.Confirmations) assert.Equal(t, TXHash, actual.Transaction.Hash()) }) @@ -1364,12 +1488,12 @@ func testRPCProtocol(t *testing.T, doRPCCall func(string, string, *testing.T) [] require.NoError(t, json.Unmarshal(res, actual)) checkNep17TransfersAux(t, e, actual, sent, rcvd) } - t.Run("time frame only", func(t *testing.T) { testNEP17T(t, 4, 5, 0, 0, []int{3, 4, 5, 6}, []int{1, 2}) }) + t.Run("time frame only", func(t *testing.T) { testNEP17T(t, 4, 5, 0, 0, []int{5, 6, 7, 8}, []int{1, 2}) }) t.Run("no res", func(t *testing.T) { testNEP17T(t, 100, 100, 0, 0, []int{}, []int{}) }) - t.Run("limit", func(t *testing.T) { testNEP17T(t, 1, 7, 3, 0, []int{0, 1}, []int{0}) }) - t.Run("limit 2", func(t *testing.T) { testNEP17T(t, 4, 5, 2, 0, []int{3}, []int{1}) }) - t.Run("limit with page", func(t *testing.T) { testNEP17T(t, 1, 7, 3, 1, []int{2, 3}, []int{1}) }) - t.Run("limit with page 2", func(t *testing.T) { testNEP17T(t, 1, 7, 3, 2, []int{4, 5}, []int{2}) }) + t.Run("limit", func(t *testing.T) { testNEP17T(t, 1, 7, 3, 0, []int{2, 3}, []int{0}) }) + t.Run("limit 2", func(t *testing.T) { testNEP17T(t, 4, 5, 2, 0, []int{5}, []int{1}) }) + t.Run("limit with page", func(t *testing.T) { testNEP17T(t, 1, 7, 3, 1, []int{4, 5}, []int{1}) }) + t.Run("limit with page 2", func(t *testing.T) { testNEP17T(t, 1, 7, 3, 2, []int{6, 7}, []int{2}) }) }) } @@ -1474,8 +1598,8 @@ func checkNep17Balances(t *testing.T, e *executor, acc interface{}) { }, { Asset: e.chain.UtilityTokenHash(), - Amount: "80006665650", - LastUpdated: 7, + Amount: "78994306100", + LastUpdated: 8, }}, Address: testchain.PrivateKeyByID(0).GetScriptHash().StringLE(), } @@ -1484,7 +1608,7 @@ func checkNep17Balances(t *testing.T, e *executor, acc interface{}) { } func checkNep17Transfers(t *testing.T, e *executor, acc interface{}) { - checkNep17TransfersAux(t, e, acc, []int{0, 1, 2, 3, 4, 5, 6, 7, 8}, []int{0, 1, 2, 3, 4, 5, 6}) + checkNep17TransfersAux(t, e, acc, []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, []int{0, 1, 2, 3, 4, 5, 6}) } func checkNep17TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rcvd []int) { @@ -1493,6 +1617,11 @@ func checkNep17TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rc rublesHash, err := util.Uint160DecodeStringLE(testContractHash) require.NoError(t, err) + blockDepositGAS, err := e.chain.GetBlock(e.chain.GetHeaderHash(8)) + require.NoError(t, err) + require.Equal(t, 1, len(blockDepositGAS.Transactions)) + txDepositGAS := blockDepositGAS.Transactions[0] + blockDeploy2, err := e.chain.GetBlock(e.chain.GetHeaderHash(7)) require.NoError(t, err) require.Equal(t, 1, len(blockDeploy2.Transactions)) @@ -1541,6 +1670,23 @@ func checkNep17TransfersAux(t *testing.T, e *executor, acc interface{}, sent, rc // duplicate the Server method. expected := result.NEP17Transfers{ Sent: []result.NEP17Transfer{ + { + Timestamp: blockDepositGAS.Timestamp, + Asset: e.chain.UtilityTokenHash(), + Address: address.Uint160ToString(e.chain.GetNotaryContractScriptHash()), + Amount: "1000000000", + Index: 8, + NotifyIndex: 0, + TxHash: txDepositGAS.Hash(), + }, + { + Timestamp: blockDepositGAS.Timestamp, + Asset: e.chain.UtilityTokenHash(), + Address: "", // burn + Amount: big.NewInt(txDepositGAS.SystemFee + txDepositGAS.NetworkFee).String(), + Index: 8, + TxHash: blockDepositGAS.Hash(), + }, { Timestamp: blockDeploy2.Timestamp, Asset: e.chain.UtilityTokenHash(), diff --git a/pkg/rpc/server/testdata/testblocks.acc b/pkg/rpc/server/testdata/testblocks.acc index d8320664d243bb798d2ba3d249fbc6e524d007b9..48120fe7473a007b56c50c5eb4087d31ad17bf41 100644 GIT binary patch delta 3331 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 XV0>0+(&;2Mu8S~kW;I0Y>YM)o?q4#k delta 1888 zcmV-m2cP(jP5V0m2ay3w1ldSzXpvALe}mL2a8jfDUnw{4?~wc`73{5q9XY%&{l}yu zgfEY2M8;N}6;pJ;qE=m$AJRKBLwYo*UYJ}r(uV&rP%s78+zddi9gFo*(?S4H?3nFh zG%y|R(P`7!%ih52rp$C#g#>N9mu9%YI`lj=sqMF%+wdfBG|iK^82~E{6}Br5MQPud z3_#u+Aj~c0mf+mrsH`Q{FbCP*E=*QYm+nlCx1grptIHb4B5}ujOtB(1V2igh>qgnq z3e8avix~mZ+C9K39l(=e7?qQ26$`V}0o?;h6wK<1Wvc5xb1&nM#IeK3?_Mlo!X~&A zLIqS($bT?81L6JiM~Yr?=Jjpa{r;nkfC13G`(kpl;`%n1QUndA+DL3@cL4wZ0+TNh z8-JEtu_tJ&65Eu6KSh2{$ZfD_oH#sn1>L0W=#Kwl^Ir^O{})biznEE}P)8AUdmp29 zN`_Cd%kKZ*y;4?i)Hw`5LN^O8!okS!AWfHSxkd$EPe;=Z9-?6mh~0~%ukSJfOl_X` zn{eTF)*!l4HiH)1Krt54FNKk@9{`1(2Q<-(R2n;*|ljXmpB`VHlv3c?VyU zatK(H<_Xu6*aw=Ey$VRPzz7@xlW!b*vw#aq0zi)`{*$o9Y`g|jCZ9N%Hq&ue009O0J-j=RGj%R2OzCm5E&?k;0PzM+7;u=m8+|Ba}c04bNWN(wv9V#fM0ssI2 z0002sfeQ}8{+$1`Cb%9f7A7s%%^TV}H4;Ob>67!*7_x@=%;!=@4sB+c zGDM^z_qDqMZAQEzhUC@DSmeI=MT}EH3_#=ItbF8*`nK!qu{y(&#ocMnM633ZumULliV7@(5`5aJ+HZU2HT zr|ORGDNsD7T)9i%a@HyqHsQPE{q^A2@aSff1`!|x+(>L_lPVD)f57lc+#u>_n48_k zl8f8|Y48c$czI?awWU*#{iV@vvQ5mx1-5|RB^bQJdjIY&KuY5SxGkmYPa)00!&_0P zZ45vs4Z&o?d5cSDl<5Mvl!AN8A7nV`eE8D6oEHRrbla}KXUI$2xi}ulvKiyyMA@jC zUIoEKdW>NC0BQmOMS*#43_wrbkA}<1s7xiL$Jn{MM+&m;aig?pinVQcKA#utYfe%Y zrBaR6jejLQ1#?kPPiL7pC?_V$m|K!wmaR9-PR5gA7@(uB5&<9vj~Ot>bx@)S@#$6n z)x2-2#HPPz9W;Zo_r#low+X(J&J!RB-AHU`cL4wZ1(Pok8-L^=!UPzHH*@YLe}nYI z{E%m-eia)kb^!n(-2G%+H8mxXrOPy%gbO!TQlHQ4ci!UxH(JH0b4w1k0eDj_@23nv z4b4y%B^s7T+VSXM6iVZ>XqY}#7bY!XoRUawZZdCWg`Kr)!Dc+T1W{uJ)Z9s3%;@Fy z)P`avTl46&RYk^Iy$nFV-l`#wRaAH_)0!McT{s%k+5|pptAsshc;c=*6q#5dIZJy8 zdsON_&p+5U^#pG@{pk?=dHDnjWn3lSETu`4VHlOOYZcA`AR0Esn#p^ceFHF!CVUt-GAOzk>Y-p2x7a)JI#pT8DTy?>ap6R%R3({Ok84~x{ zZI@2c?B89rl0mQ3Z+k9KtjgaVp!=E zdj84JmTSD`8|-~apRp&)XjelzG9Wo!%BMmWfZ2w*C;lF`WfOt4)_@+qa?0PQn(+I& zMchST+0hI@16>lL5Lg5~FfQ=~Ej?1VWm}jZ8FQ;xg5YJGJXs++-`HP7i~p$#YuPrs zHVgBK6F!zrX1lfK&hx%xrdE+>vtbyY0U!+-J=(`+x8FL`zY?kTvKF>=Q^G)oCKloY zL^Xwqpj?w68XyVZNNi|#0RR98lP?h)e~%b~hhI9wh|+XRXxwLqw|k^M!hhhj^J;u5 zXmIF+#pL|Krj>02@@|KsnYgnmnkxWHCR&ktq#9RXZdAKXj|@PQOu5<)Cr&alnZc&v zgcr!dH?X@^Gu