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 }