2022-10-05 06:44:10 +00:00
|
|
|
package query_test
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
|
|
|
"fmt"
|
|
|
|
"regexp"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/internal/random"
|
2022-10-05 06:44:10 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/internal/testcli"
|
2021-07-16 14:47:40 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
2021-07-21 15:27:09 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
2021-07-16 14:47:40 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
|
|
|
"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"
|
2022-07-08 14:28:29 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
|
2021-07-16 14:47:40 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestQueryTx(t *testing.T) {
|
2022-10-05 06:44:10 +00:00
|
|
|
e := testcli.NewExecutorSuspended(t)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
2022-10-05 06:44:10 +00:00
|
|
|
w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
|
2021-07-16 14:47:40 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
transferArgs := []string{
|
|
|
|
"neo-go", "wallet", "nep17", "transfer",
|
|
|
|
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
2022-10-05 06:44:10 +00:00
|
|
|
"--wallet", testcli.ValidatorWallet,
|
2021-07-16 14:47:40 +00:00
|
|
|
"--to", w.Accounts[0].Address,
|
|
|
|
"--token", "NEO",
|
2022-10-05 06:44:10 +00:00
|
|
|
"--from", testcli.ValidatorAddr,
|
2021-09-15 09:40:30 +00:00
|
|
|
"--force",
|
2021-07-16 14:47:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
e.In.WriteString("one\r")
|
|
|
|
e.Run(t, append(transferArgs, "--amount", "1")...)
|
2022-10-05 06:44:10 +00:00
|
|
|
line := e.GetNextLine(t)
|
2021-07-16 14:47:40 +00:00
|
|
|
txHash, err := util.Uint256DecodeStringLE(line)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tx, ok := e.Chain.GetMemPool().TryGetValue(txHash)
|
|
|
|
require.True(t, ok)
|
|
|
|
|
|
|
|
args := []string{"neo-go", "query", "tx", "--rpc-endpoint", "http://" + e.RPC.Addr}
|
|
|
|
e.Run(t, append(args, txHash.StringLE())...)
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `Hash:\s+`+txHash.StringLE())
|
|
|
|
e.CheckNextLine(t, `OnChain:\s+false`)
|
|
|
|
e.CheckNextLine(t, `ValidUntil:\s+`+strconv.FormatUint(uint64(tx.ValidUntilBlock), 10))
|
|
|
|
e.CheckEOF(t)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
go e.Chain.Run()
|
cli: fix race in TestQueryTx
Problem - failing TestQueryTx test:
```
=== RUN TestQueryTx/verbose/FAULT
=== CONT TestQueryTx
logger.go:130: 2022-10-26T10:47:51.414Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.415Z DEBUG processing rpc request {"method": "getnativecontracts", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.612Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.615Z DEBUG processing rpc request {"method": "invokefunction", "params": "[11fdb7bc30a306a60dac874711a2b37b7da402c4 randomMethod ]"}
logger.go:130: 2022-10-26T10:47:51.617Z DEBUG processing rpc request {"method": "getblockcount", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.617Z INFO persisted to disk {"blocks": 2, "keys": 154, "headerHeight": 2, "blockHeight": 2, "took": "260.704µs"}
logger.go:130: 2022-10-26T10:47:51.618Z DEBUG processing rpc request {"method": "calculatenetworkfee", "params": "[AIpp7dreAw8AAAAAAAAAAAAAAAAABQAAAAHYzFqQTVJvyabKtVugLJpv54nJVgAAK8IfDAxyYW5kb21NZXRob2QMFMQCpH17s6IRR4esDaYGozC8t/0RQWJ9W1IBACoRDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIRQZ7Q3Do=]"}
logger.go:130: 2022-10-26T10:47:51.712Z DEBUG processing rpc request {"method": "sendrawtransaction", "params": "[AIpp7dreAw8AAAAAABQbEgAAAAAABQAAAAHYzFqQTVJvyabKtVugLJpv54nJVgAAK8IfDAxyYW5kb21NZXRob2QMFMQCpH17s6IRR4esDaYGozC8t/0RQWJ9W1IBQgxAO2nxSMSRNFqBD5lOA37E9Px+nYDGMy6IqZromHXFtVTYD1c1hdUK4vTccoOr2AksdGwDsdQ8qIGJhXdEDxv8NSoRDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIRQZ7Q3Do=]"}
logger.go:130: 2022-10-26T10:47:51.713Z DEBUG done processing headers {"headerIndex": 3, "blockHeight": 2, "took": "228.756µs"}
logger.go:130: 2022-10-26T10:47:51.813Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.815Z DEBUG processing rpc request {"method": "getnativecontracts", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.923Z DEBUG processing rpc request {"method": "getrawtransaction", "params": "[22bbb08d3f4b9e601a05c1bb1f7ac456d44bfad013287599bf3f843a75b30076 1]"}
=== CONT TestQueryTx/verbose/FAULT
executor.go:238:
Error Trace: executor.go:238
executor.go:234
query_test.go:119
query_test.go:97
Error: Expect "OnChain: false" to match "OnChain:\s+true"
Test: TestQueryTx/verbose/FAULT
```
chain.GetTransaction is looking into mempool also, so we need to check for the
AER instead of transaction.
2022-10-26 11:03:56 +00:00
|
|
|
require.Eventually(t, func() bool { _, aerErr := e.Chain.GetAppExecResults(txHash, trigger.Application); return aerErr == nil }, time.Second*2, time.Millisecond*50)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
e.Run(t, append(args, txHash.StringLE())...)
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `Hash:\s+`+txHash.StringLE())
|
|
|
|
e.CheckNextLine(t, `OnChain:\s+true`)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
cli: fix race in TestQueryTx
Problem - failing TestQueryTx test:
```
=== RUN TestQueryTx/verbose/FAULT
=== CONT TestQueryTx
logger.go:130: 2022-10-26T10:47:51.414Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.415Z DEBUG processing rpc request {"method": "getnativecontracts", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.612Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.615Z DEBUG processing rpc request {"method": "invokefunction", "params": "[11fdb7bc30a306a60dac874711a2b37b7da402c4 randomMethod ]"}
logger.go:130: 2022-10-26T10:47:51.617Z DEBUG processing rpc request {"method": "getblockcount", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.617Z INFO persisted to disk {"blocks": 2, "keys": 154, "headerHeight": 2, "blockHeight": 2, "took": "260.704µs"}
logger.go:130: 2022-10-26T10:47:51.618Z DEBUG processing rpc request {"method": "calculatenetworkfee", "params": "[AIpp7dreAw8AAAAAAAAAAAAAAAAABQAAAAHYzFqQTVJvyabKtVugLJpv54nJVgAAK8IfDAxyYW5kb21NZXRob2QMFMQCpH17s6IRR4esDaYGozC8t/0RQWJ9W1IBACoRDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIRQZ7Q3Do=]"}
logger.go:130: 2022-10-26T10:47:51.712Z DEBUG processing rpc request {"method": "sendrawtransaction", "params": "[AIpp7dreAw8AAAAAABQbEgAAAAAABQAAAAHYzFqQTVJvyabKtVugLJpv54nJVgAAK8IfDAxyYW5kb21NZXRob2QMFMQCpH17s6IRR4esDaYGozC8t/0RQWJ9W1IBQgxAO2nxSMSRNFqBD5lOA37E9Px+nYDGMy6IqZromHXFtVTYD1c1hdUK4vTccoOr2AksdGwDsdQ8qIGJhXdEDxv8NSoRDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIRQZ7Q3Do=]"}
logger.go:130: 2022-10-26T10:47:51.713Z DEBUG done processing headers {"headerIndex": 3, "blockHeight": 2, "took": "228.756µs"}
logger.go:130: 2022-10-26T10:47:51.813Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.815Z DEBUG processing rpc request {"method": "getnativecontracts", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.923Z DEBUG processing rpc request {"method": "getrawtransaction", "params": "[22bbb08d3f4b9e601a05c1bb1f7ac456d44bfad013287599bf3f843a75b30076 1]"}
=== CONT TestQueryTx/verbose/FAULT
executor.go:238:
Error Trace: executor.go:238
executor.go:234
query_test.go:119
query_test.go:97
Error: Expect "OnChain: false" to match "OnChain:\s+true"
Test: TestQueryTx/verbose/FAULT
```
chain.GetTransaction is looking into mempool also, so we need to check for the
AER instead of transaction.
2022-10-26 11:03:56 +00:00
|
|
|
_, height, err := e.Chain.GetTransaction(txHash)
|
2021-07-16 14:47:40 +00:00
|
|
|
require.NoError(t, err)
|
2022-11-18 20:19:50 +00:00
|
|
|
e.CheckNextLine(t, `BlockHash:\s+`+e.Chain.GetHeaderHash(height).StringLE())
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `Success:\s+true`)
|
|
|
|
e.CheckEOF(t)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
t.Run("verbose", func(t *testing.T) {
|
|
|
|
e.Run(t, append(args, "--verbose", txHash.StringLE())...)
|
2022-10-05 06:44:10 +00:00
|
|
|
compareQueryTxVerbose(t, e, tx)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
t.Run("FAULT", func(t *testing.T) {
|
|
|
|
e.In.WriteString("one\r")
|
|
|
|
e.Run(t, "neo-go", "contract", "invokefunction",
|
|
|
|
"--rpc-endpoint", "http://"+e.RPC.Addr,
|
2022-10-05 06:44:10 +00:00
|
|
|
"--wallet", testcli.ValidatorWallet,
|
|
|
|
"--address", testcli.ValidatorAddr,
|
2021-07-16 14:47:40 +00:00
|
|
|
"--force",
|
|
|
|
random.Uint160().StringLE(),
|
|
|
|
"randomMethod")
|
|
|
|
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `Warning:`)
|
|
|
|
e.CheckNextLine(t, "Sending transaction")
|
|
|
|
line := strings.TrimPrefix(e.GetNextLine(t), "Sent invocation transaction ")
|
2021-07-16 14:47:40 +00:00
|
|
|
txHash, err := util.Uint256DecodeStringLE(line)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
cli: fix race in TestQueryTx
Problem - failing TestQueryTx test:
```
=== RUN TestQueryTx/verbose/FAULT
=== CONT TestQueryTx
logger.go:130: 2022-10-26T10:47:51.414Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.415Z DEBUG processing rpc request {"method": "getnativecontracts", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.612Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.615Z DEBUG processing rpc request {"method": "invokefunction", "params": "[11fdb7bc30a306a60dac874711a2b37b7da402c4 randomMethod ]"}
logger.go:130: 2022-10-26T10:47:51.617Z DEBUG processing rpc request {"method": "getblockcount", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.617Z INFO persisted to disk {"blocks": 2, "keys": 154, "headerHeight": 2, "blockHeight": 2, "took": "260.704µs"}
logger.go:130: 2022-10-26T10:47:51.618Z DEBUG processing rpc request {"method": "calculatenetworkfee", "params": "[AIpp7dreAw8AAAAAAAAAAAAAAAAABQAAAAHYzFqQTVJvyabKtVugLJpv54nJVgAAK8IfDAxyYW5kb21NZXRob2QMFMQCpH17s6IRR4esDaYGozC8t/0RQWJ9W1IBACoRDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIRQZ7Q3Do=]"}
logger.go:130: 2022-10-26T10:47:51.712Z DEBUG processing rpc request {"method": "sendrawtransaction", "params": "[AIpp7dreAw8AAAAAABQbEgAAAAAABQAAAAHYzFqQTVJvyabKtVugLJpv54nJVgAAK8IfDAxyYW5kb21NZXRob2QMFMQCpH17s6IRR4esDaYGozC8t/0RQWJ9W1IBQgxAO2nxSMSRNFqBD5lOA37E9Px+nYDGMy6IqZromHXFtVTYD1c1hdUK4vTccoOr2AksdGwDsdQ8qIGJhXdEDxv8NSoRDCECs2Ir9AF73+MXxYrtX0x1PyBrfbiWBG+n13S7xL9/jcIRQZ7Q3Do=]"}
logger.go:130: 2022-10-26T10:47:51.713Z DEBUG done processing headers {"headerIndex": 3, "blockHeight": 2, "took": "228.756µs"}
logger.go:130: 2022-10-26T10:47:51.813Z DEBUG processing rpc request {"method": "getversion", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.815Z DEBUG processing rpc request {"method": "getnativecontracts", "params": "[]"}
logger.go:130: 2022-10-26T10:47:51.923Z DEBUG processing rpc request {"method": "getrawtransaction", "params": "[22bbb08d3f4b9e601a05c1bb1f7ac456d44bfad013287599bf3f843a75b30076 1]"}
=== CONT TestQueryTx/verbose/FAULT
executor.go:238:
Error Trace: executor.go:238
executor.go:234
query_test.go:119
query_test.go:97
Error: Expect "OnChain: false" to match "OnChain:\s+true"
Test: TestQueryTx/verbose/FAULT
```
chain.GetTransaction is looking into mempool also, so we need to check for the
AER instead of transaction.
2022-10-26 11:03:56 +00:00
|
|
|
require.Eventually(t, func() bool { _, aerErr := e.Chain.GetAppExecResults(txHash, trigger.Application); return aerErr == nil }, time.Second*2, time.Millisecond*50)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
tx, _, err := e.Chain.GetTransaction(txHash)
|
|
|
|
require.NoError(t, err)
|
|
|
|
e.Run(t, append(args, "--verbose", txHash.StringLE())...)
|
2022-10-05 06:44:10 +00:00
|
|
|
compareQueryTxVerbose(t, e, tx)
|
2021-07-16 14:47:40 +00:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("invalid", func(t *testing.T) {
|
|
|
|
t.Run("missing tx argument", func(t *testing.T) {
|
|
|
|
e.RunWithError(t, args...)
|
|
|
|
})
|
2022-08-05 10:32:37 +00:00
|
|
|
t.Run("excessive arguments", func(t *testing.T) {
|
|
|
|
e.RunWithError(t, append(args, txHash.StringLE(), txHash.StringLE())...)
|
|
|
|
})
|
2021-07-16 14:47:40 +00:00
|
|
|
t.Run("invalid hash", func(t *testing.T) {
|
|
|
|
e.RunWithError(t, append(args, "notahash")...)
|
|
|
|
})
|
|
|
|
t.Run("good hash, missing tx", func(t *testing.T) {
|
|
|
|
e.RunWithError(t, append(args, random.Uint256().StringLE())...)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-10-05 06:44:10 +00:00
|
|
|
func compareQueryTxVerbose(t *testing.T, e *testcli.Executor, tx *transaction.Transaction) {
|
|
|
|
e.CheckNextLine(t, `Hash:\s+`+tx.Hash().StringLE())
|
|
|
|
e.CheckNextLine(t, `OnChain:\s+true`)
|
2021-07-16 14:47:40 +00:00
|
|
|
_, height, err := e.Chain.GetTransaction(tx.Hash())
|
|
|
|
require.NoError(t, err)
|
2022-11-18 20:19:50 +00:00
|
|
|
e.CheckNextLine(t, `BlockHash:\s+`+e.Chain.GetHeaderHash(height).StringLE())
|
2021-07-16 14:47:40 +00:00
|
|
|
|
|
|
|
res, _ := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, fmt.Sprintf(`Success:\s+%t`, res[0].Execution.VMState == vmstate.Halt))
|
2021-07-16 14:47:40 +00:00
|
|
|
for _, s := range tx.Signers {
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, fmt.Sprintf(`Signer:\s+%s\s*\(%s\)`, address.Uint160ToString(s.Account), s.Scopes.String()))
|
2021-07-16 14:47:40 +00:00
|
|
|
}
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `SystemFee:\s+`+fixedn.Fixed8(tx.SystemFee).String()+" GAS$")
|
|
|
|
e.CheckNextLine(t, `NetworkFee:\s+`+fixedn.Fixed8(tx.NetworkFee).String()+" GAS$")
|
|
|
|
e.CheckNextLine(t, `Script:\s+`+regexp.QuoteMeta(base64.StdEncoding.EncodeToString(tx.Script)))
|
2021-09-14 12:02:54 +00:00
|
|
|
c := vm.NewContext(tx.Script)
|
|
|
|
n := 0
|
|
|
|
for ; c.NextIP() < c.LenInstr(); _, _, err = c.Next() {
|
|
|
|
require.NoError(t, err)
|
|
|
|
n++
|
|
|
|
}
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckScriptDump(t, n)
|
2021-07-16 14:47:40 +00:00
|
|
|
|
2022-07-08 14:28:29 +00:00
|
|
|
if res[0].Execution.VMState != vmstate.Halt {
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `Exception:\s+`+regexp.QuoteMeta(res[0].Execution.FaultException))
|
2021-07-16 14:47:40 +00:00
|
|
|
}
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckEOF(t)
|
2021-07-16 14:47:40 +00:00
|
|
|
}
|
2021-07-22 18:10:32 +00:00
|
|
|
|
|
|
|
func TestQueryHeight(t *testing.T) {
|
2022-10-05 06:44:10 +00:00
|
|
|
e := testcli.NewExecutor(t, true)
|
2021-07-22 18:10:32 +00:00
|
|
|
|
2022-08-05 10:32:37 +00:00
|
|
|
args := []string{"neo-go", "query", "height", "--rpc-endpoint", "http://" + e.RPC.Addr}
|
|
|
|
e.Run(t, args...)
|
2022-10-05 06:44:10 +00:00
|
|
|
e.CheckNextLine(t, `^Latest block: [0-9]+$`)
|
|
|
|
e.CheckNextLine(t, `^Validated state: [0-9]+$`)
|
|
|
|
e.CheckEOF(t)
|
2022-08-05 10:32:37 +00:00
|
|
|
t.Run("excessive arguments", func(t *testing.T) {
|
|
|
|
e.RunWithError(t, append(args, "something")...)
|
|
|
|
})
|
2021-07-22 18:10:32 +00:00
|
|
|
}
|