github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/cmd/u2u/launcher/txtracer_test.go (about)

     1  package launcher
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"io/ioutil"
     7  	"log"
     8  	"net/http"
     9  	"strconv"
    10  	"strings"
    11  	"testing"
    12  	"time"
    13  
    14  	"github.com/stretchr/testify/require"
    15  	"github.com/unicornultrafoundation/go-u2u/evmcore/txtracer"
    16  )
    17  
    18  func TestTxTracing(t *testing.T) {
    19  
    20  	// Start test node on random ports and keep it running for another requests
    21  	port := strconv.Itoa(trulyRandInt(10000, 65536))
    22  	wsport := strconv.Itoa(trulyRandInt(10000, 65536))
    23  	cliNode := exec(t,
    24  		"--fakenet", "1/1", "--enabletxtracer", "--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none",
    25  		"--ws", "--ws.port", wsport, "--http", "--http.api", "eth,web3,net,txpool,trace", "--http.port", port, "--allow-insecure-unlock")
    26  
    27  	// Wait for node to start
    28  	endpoint := "ws://127.0.0.1:" + wsport
    29  	waitForEndpoint(t, endpoint, 60*time.Second)
    30  
    31  	// Deploy a smart contract from the testdata javascript file
    32  	cliConsoleDeploy := exec(t, "attach", "--datadir", cliNode.Datadir, "--exec", "loadScript('testdata/txtracer_test.js')")
    33  	contractAddress := string(*cliConsoleDeploy.GetOutPipeData())
    34  	contractAddress = contractAddress[strings.Index(contractAddress, "0x") : len(contractAddress)-1]
    35  	cliConsoleDeploy.WaitExit()
    36  
    37  	abi := `[{"inputs":[],"name":"deploy","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getA","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_a","type":"uint256"}],"name":"setA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_a","type":"uint256"}],"name":"setInA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"tst","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]`
    38  
    39  	cliConsole := exec(t, "attach", "--datadir", cliNode.Datadir)
    40  	cliConsoleOutput := *cliConsole.GetOutDataTillCursor()
    41  
    42  	// Initialize test contract for interaction
    43  	cliConsole.InputLine("var abi=" + abi)
    44  	cliConsoleOutput = *cliConsole.GetOutDataTillCursor()
    45  	cliConsole.InputLine(`var testContract = u2u.contract(abi)`)
    46  	cliConsoleOutput = *cliConsole.GetOutDataTillCursor()
    47  	cliConsole.InputLine("testContract = testContract.at('" + contractAddress + "')")
    48  	cliConsoleOutput = *cliConsole.GetOutDataTillCursor()
    49  
    50  	// Call simple contract call to check created trace
    51  	cliConsole.InputLine("testContract.setA.sendTransaction(24, {from:u2u.accounts[1]})")
    52  	cliConsoleOutput = *cliConsole.GetOutDataTillCursor()
    53  	txHashCall := cliConsoleOutput[strings.Index(cliConsoleOutput, "0x") : len(cliConsoleOutput)-3]
    54  
    55  	cliConsole.InputLine("testContract.deploy.sendTransaction({from:u2u.accounts[1]})")
    56  	cliConsoleOutput = *cliConsole.GetOutDataTillCursor()
    57  	txHashDeploy := cliConsoleOutput[strings.Index(cliConsoleOutput, "0x") : len(cliConsoleOutput)-3]
    58  	time.Sleep(5000 * time.Millisecond)
    59  
    60  	// Close node console
    61  	cliConsole.InputLine("exit")
    62  	cliConsole.WaitExit()
    63  
    64  	traceResult1, err := getTrace(txHashCall, port)
    65  	if err != nil {
    66  		log.Fatalln(err)
    67  	}
    68  
    69  	traceResult2, err := getTrace(txHashDeploy, port)
    70  	if err != nil {
    71  		log.Fatalln(err)
    72  	}
    73  
    74  	// Stop test node
    75  	cliNode.Kill()
    76  	cliNode.WaitExit()
    77  
    78  	// Compare results
    79  	// Test first transaction result trace, which should be
    80  	// just a simple call to a contract function
    81  	require.Equal(t, traceResult1.Result[0].TraceType, "call")
    82  
    83  	// Test second transaction result trace, which should be
    84  	// call to a contract, which will create a new contract and
    85  	// call a two other functions on new contract
    86  	require.Equal(t, traceResult2.Result[0].TraceType, "call")
    87  	require.Equal(t, traceResult2.Result[1].TraceType, "create")
    88  	require.Equal(t, traceResult2.Result[2].TraceType, "call")
    89  	require.Equal(t, traceResult2.Result[2].TraceType, "call")
    90  
    91  	// Check the addresses of inner traces
    92  	require.Equal(t, len(traceResult2.Result[0].TraceAddress), 0)
    93  	require.Equal(t, int(traceResult2.Result[1].TraceAddress[0]), 0)
    94  	require.Equal(t, int(traceResult2.Result[2].TraceAddress[0]), 1)
    95  	require.Equal(t, int(traceResult2.Result[3].TraceAddress[0]), 2)
    96  }
    97  
    98  func getTrace(txHash string, nodePort string) (response, error) {
    99  	jsonStr := []byte(`{"method":"trace_transaction","params":["` + txHash + `"],"id":1,"jsonrpc":"2.0"}`)
   100  	resp, err := http.Post("http://127.0.0.1:"+nodePort, "application/json", bytes.NewBuffer(jsonStr))
   101  	if err != nil {
   102  		log.Fatalln(err)
   103  	}
   104  
   105  	//We Read the response body on the line below.
   106  	body, err := ioutil.ReadAll(resp.Body)
   107  	if err != nil {
   108  		log.Fatalln(err)
   109  	}
   110  
   111  	//Convert the body to type string
   112  	var res response
   113  	err = json.Unmarshal(body, &res)
   114  	return res, err
   115  }
   116  
   117  type response struct {
   118  	Jsonrpc string
   119  	Id      int64
   120  	Result  []txtracer.ActionTrace
   121  }