github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/cli/util/util_test.go (about)

     1  package util_test
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/nspcc-dev/neo-go/internal/testcli"
    12  	"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
    13  	"github.com/nspcc-dev/neo-go/pkg/util"
    14  	"github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
    15  	"github.com/nspcc-dev/neo-go/pkg/wallet"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestUtilConvert(t *testing.T) {
    20  	e := testcli.NewExecutor(t, false)
    21  
    22  	e.Run(t, "neo-go", "util", "convert", util.Uint160{1, 2, 3}.StringLE())
    23  	e.CheckNextLine(t, "f975")                                                                             // int to hex
    24  	e.CheckNextLine(t, "\\+XU=")                                                                           // int to base64
    25  	e.CheckNextLine(t, "NKuyBkoGdZZSLyPbJEetheRhMrGSCQx7YL")                                               // BE to address
    26  	e.CheckNextLine(t, "NL1JGiyJXdTkvFksXbFxgLJcWLj8Ewe7HW")                                               // LE to address
    27  	e.CheckNextLine(t, "Hex to String")                                                                    // hex to string
    28  	e.CheckNextLine(t, "5753853598078696051256155186041784866529345536")                                   // hex to int
    29  	e.CheckNextLine(t, "0102030000000000000000000000000000000000")                                         // swap endianness
    30  	e.CheckNextLine(t, "Base64 to String")                                                                 // base64 to string
    31  	e.CheckNextLine(t, "368753434210909009569191652203865891677393101439813372294890211308228051")         // base64 to bigint
    32  	e.CheckNextLine(t, "30303030303030303030303030303030303030303030303030303030303030303030303330323031") // string to hex
    33  	e.CheckNextLine(t, "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzMDIwMQ==")                         // string to base64
    34  	e.CheckEOF(t)
    35  }
    36  
    37  func TestUtilOps(t *testing.T) {
    38  	e := testcli.NewExecutor(t, false)
    39  	base64Str := "EUA="
    40  	hexStr := "1140"
    41  
    42  	check := func(t *testing.T) {
    43  		e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER")
    44  		e.CheckNextLine(t, "PUSH1")
    45  		e.CheckNextLine(t, "RET")
    46  		e.CheckEOF(t)
    47  	}
    48  
    49  	e.Run(t, "neo-go", "util", "ops", base64Str) // base64
    50  	check(t)
    51  
    52  	e.Run(t, "neo-go", "util", "ops", hexStr) // base64 is checked firstly by default, but it's invalid script if decoded from base64
    53  	e.CheckNextLine(t, "INDEX.*OPCODE.*PARAMETER")
    54  	e.CheckNextLine(t, ".*ERROR: incorrect opcode")
    55  	e.CheckEOF(t)
    56  
    57  	e.Run(t, "neo-go", "util", "ops", "--hex", hexStr) // explicitly specify hex encoding
    58  	check(t)
    59  
    60  	e.RunWithError(t, "neo-go", "util", "ops", "%&~*") // unknown encoding
    61  
    62  	tmp := filepath.Join(t.TempDir(), "script_base64.txt")
    63  	require.NoError(t, os.WriteFile(tmp, []byte(base64Str), os.ModePerm))
    64  	e.Run(t, "neo-go", "util", "ops", "--in", tmp) // base64 from file
    65  	check(t)
    66  
    67  	tmp = filepath.Join(t.TempDir(), "script_hex.txt")
    68  	require.NoError(t, os.WriteFile(tmp, []byte(hexStr), os.ModePerm))
    69  	e.Run(t, "neo-go", "util", "ops", "--hex", "--in", tmp) // hex from file
    70  	check(t)
    71  }
    72  
    73  func TestUtilCancelTx(t *testing.T) {
    74  	e := testcli.NewExecutorSuspended(t)
    75  
    76  	w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
    77  	require.NoError(t, err)
    78  
    79  	transferArgs := []string{
    80  		"neo-go", "wallet", "nep17", "transfer",
    81  		"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
    82  		"--wallet", testcli.ValidatorWallet,
    83  		"--to", w.Accounts[0].Address,
    84  		"--token", "NEO",
    85  		"--from", testcli.ValidatorAddr,
    86  		"--force",
    87  	}
    88  	args := []string{"neo-go", "util", "canceltx",
    89  		"-r", "http://" + e.RPC.Addresses()[0],
    90  		"--wallet", testcli.ValidatorWallet,
    91  		"--address", testcli.ValidatorAddr}
    92  
    93  	e.In.WriteString("one\r")
    94  	e.Run(t, append(transferArgs, "--amount", "1")...)
    95  	line := e.GetNextLine(t)
    96  	txHash, err := util.Uint256DecodeStringLE(line)
    97  	require.NoError(t, err)
    98  
    99  	_, ok := e.Chain.GetMemPool().TryGetValue(txHash)
   100  	require.True(t, ok)
   101  
   102  	t.Run("invalid", func(t *testing.T) {
   103  		t.Run("missing tx argument", func(t *testing.T) {
   104  			e.RunWithError(t, args...)
   105  		})
   106  		t.Run("excessive arguments", func(t *testing.T) {
   107  			e.RunWithError(t, append(args, txHash.StringLE(), txHash.StringLE())...)
   108  		})
   109  		t.Run("invalid hash", func(t *testing.T) {
   110  			e.RunWithError(t, append(args, "notahash")...)
   111  		})
   112  		t.Run("not signed by main signer", func(t *testing.T) {
   113  			e.In.WriteString("one\r")
   114  			e.RunWithError(t, "neo-go", "util", "canceltx",
   115  				"-r", "http://"+e.RPC.Addresses()[0],
   116  				"--wallet", testcli.ValidatorWallet,
   117  				"--address", testcli.MultisigAddr, txHash.StringLE())
   118  		})
   119  		t.Run("wrong rpc endpoint", func(t *testing.T) {
   120  			e.In.WriteString("one\r")
   121  			e.RunWithError(t, "neo-go", "util", "canceltx",
   122  				"-r", "http://localhost:20331",
   123  				"--wallet", testcli.ValidatorWallet, txHash.StringLE())
   124  		})
   125  	})
   126  
   127  	e.In.WriteString("one\r")
   128  	e.Run(t, append(args, txHash.StringLE())...)
   129  	resHash, err := util.Uint256DecodeStringLE(e.GetNextLine(t))
   130  	require.NoError(t, err)
   131  
   132  	_, _, err = e.Chain.GetTransaction(resHash)
   133  	require.NoError(t, err)
   134  	e.CheckEOF(t)
   135  	go e.Chain.Run()
   136  
   137  	require.Eventually(t, func() bool {
   138  		_, aerErr := e.Chain.GetAppExecResults(resHash, trigger.Application)
   139  		return aerErr == nil
   140  	}, time.Second*2, time.Millisecond*50)
   141  }
   142  
   143  func TestAwaitUtilCancelTx(t *testing.T) {
   144  	e := testcli.NewExecutor(t, true)
   145  
   146  	w, err := wallet.NewWalletFromFile("../testdata/testwallet.json")
   147  	require.NoError(t, err)
   148  
   149  	transferArgs := []string{
   150  		"neo-go", "wallet", "nep17", "transfer",
   151  		"--rpc-endpoint", "http://" + e.RPC.Addresses()[0],
   152  		"--wallet", testcli.ValidatorWallet,
   153  		"--to", w.Accounts[0].Address,
   154  		"--token", "NEO",
   155  		"--from", testcli.ValidatorAddr,
   156  		"--force",
   157  	}
   158  	args := []string{"neo-go", "util", "canceltx",
   159  		"-r", "http://" + e.RPC.Addresses()[0],
   160  		"--wallet", testcli.ValidatorWallet,
   161  		"--address", testcli.ValidatorAddr,
   162  		"--await"}
   163  
   164  	e.In.WriteString("one\r")
   165  	e.Run(t, append(transferArgs, "--amount", "1")...)
   166  	line := e.GetNextLine(t)
   167  	txHash, err := util.Uint256DecodeStringLE(line)
   168  	require.NoError(t, err)
   169  
   170  	_, ok := e.Chain.GetMemPool().TryGetValue(txHash)
   171  	require.True(t, ok)
   172  
   173  	// Allow both cases: either target or conflicting tx acceptance.
   174  	e.In.WriteString("one\r")
   175  	err = e.RunUnchecked(t, append(args, txHash.StringLE())...)
   176  	switch {
   177  	case err == nil:
   178  		response := e.GetNextLine(t)
   179  		require.Equal(t, "Conflicting transaction accepted", response)
   180  		resHash, _ := e.CheckAwaitableTxPersisted(t)
   181  		require.NotEqual(t, resHash, txHash)
   182  	case strings.Contains(err.Error(), fmt.Sprintf("target transaction %s is accepted", txHash)) ||
   183  		strings.Contains(err.Error(), fmt.Sprintf("failed to send conflicting transaction: Invalid transaction attribute (-507) - invalid attribute: conflicting transaction %s is already on chain", txHash)):
   184  		tx, _ := e.GetTransaction(t, txHash)
   185  		aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
   186  		require.NoError(t, err)
   187  		require.Equal(t, 1, len(aer))
   188  		require.Equal(t, vmstate.Halt, aer[0].VMState)
   189  	default:
   190  		t.Fatal(fmt.Errorf("unexpected error: %w", err))
   191  	}
   192  }