diff --git a/go/common/tracers/debug_logs.go b/go/common/tracers/debug_logs.go index 7c9a5c9836..110e1bb828 100644 --- a/go/common/tracers/debug_logs.go +++ b/go/common/tracers/debug_logs.go @@ -11,11 +11,11 @@ import ( // DebugLogs are the logs returned when using the DebugGetLogs endpoint type DebugLogs struct { - RelAddress1 *gethcommon.Hash `json:"relAddress1"` - RelAddress2 *gethcommon.Hash `json:"relAddress2"` - RelAddress3 *gethcommon.Hash `json:"relAddress3"` - RelAddress4 *gethcommon.Hash `json:"relAddress4"` - LifecycleEvent bool `json:"lifecycleEvent"` + RelAddress1 *gethcommon.Address `json:"relAddress1"` + RelAddress2 *gethcommon.Address `json:"relAddress2"` + RelAddress3 *gethcommon.Address `json:"relAddress3"` + RelAddress4 *gethcommon.Address `json:"relAddress4"` + LifecycleEvent bool `json:"lifecycleEvent"` gethtypes.Log } @@ -24,20 +24,20 @@ type DebugLogs struct { // this holds a copy of the gethtypes.Log log marshaller func (l DebugLogs) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - Address string `json:"address" gencodec:"required"` - Topics []gethcommon.Hash `json:"topics" gencodec:"required"` - Data hexutil.Bytes `json:"data" gencodec:"required"` - BlockNumber uint64 `json:"blockNumber"` - TxHash gethcommon.Hash `json:"transactionHash" gencodec:"required"` - TxIndex uint `json:"transactionIndex"` - BlockHash gethcommon.Hash `json:"blockHash"` - Index uint `json:"logIndex"` - Removed bool `json:"removed"` - LifecycleEvent bool `json:"lifecycleEvent"` - RelAddress1 *gethcommon.Hash `json:"relAddress1"` - RelAddress2 *gethcommon.Hash `json:"relAddress2"` - RelAddress3 *gethcommon.Hash `json:"relAddress3"` - RelAddress4 *gethcommon.Hash `json:"relAddress4"` + Address string `json:"address" gencodec:"required"` + Topics []gethcommon.Hash `json:"topics" gencodec:"required"` + Data hexutil.Bytes `json:"data" gencodec:"required"` + BlockNumber uint64 `json:"blockNumber"` + TxHash gethcommon.Hash `json:"transactionHash" gencodec:"required"` + TxIndex uint `json:"transactionIndex"` + BlockHash gethcommon.Hash `json:"blockHash"` + Index uint `json:"logIndex"` + Removed bool `json:"removed"` + LifecycleEvent bool `json:"lifecycleEvent"` + RelAddress1 *gethcommon.Address `json:"relAddress1"` + RelAddress2 *gethcommon.Address `json:"relAddress2"` + RelAddress3 *gethcommon.Address `json:"relAddress3"` + RelAddress4 *gethcommon.Address `json:"relAddress4"` }{ l.Address.Hex(), l.Topics, diff --git a/go/enclave/storage/enclavedb/events.go b/go/enclave/storage/enclavedb/events.go index e1b2d5d1ee..5483f4bb64 100644 --- a/go/enclave/storage/enclavedb/events.go +++ b/go/enclave/storage/enclavedb/events.go @@ -203,7 +203,7 @@ func DebugGetLogs(db *sql.DB, txHash common.TxHash) ([]*tracers.DebugLogs, error } var t0, t1, t2, t3, t4 sql.NullString - var relAddress1, relAddress2, relAddress3, relAddress4 sql.NullByte + var relAddress1, relAddress2, relAddress3, relAddress4 []byte err = rows.Scan( &relAddress1, &relAddress2, @@ -229,10 +229,10 @@ func DebugGetLogs(db *sql.DB, txHash common.TxHash) ([]*tracers.DebugLogs, error } } - l.RelAddress1 = bytesToHash(relAddress1) - l.RelAddress2 = bytesToHash(relAddress2) - l.RelAddress3 = bytesToHash(relAddress3) - l.RelAddress4 = bytesToHash(relAddress4) + l.RelAddress1 = bytesToAddress(relAddress1) + l.RelAddress2 = bytesToAddress(relAddress2) + l.RelAddress3 = bytesToAddress(relAddress3) + l.RelAddress4 = bytesToAddress(relAddress4) result = append(result, &l) } @@ -244,6 +244,14 @@ func DebugGetLogs(db *sql.DB, txHash common.TxHash) ([]*tracers.DebugLogs, error return result, nil } +func bytesToAddress(b []byte) *gethcommon.Address { + if b != nil { + addr := gethcommon.BytesToAddress(b) + return &addr + } + return nil +} + // Of the log's topics, returns those that are (potentially) user addresses. A topic is considered a user address if: // - It has at least 12 leading zero bytes (since addresses are 20 bytes long, while hashes are 32) and at most 22 leading zero bytes // - It does not have associated code (meaning it's a smart-contract address) @@ -350,23 +358,6 @@ func stringToHash(ns sql.NullString) gethcommon.Hash { return result } -func bytesToHash(b sql.NullByte) *gethcommon.Hash { - result := gethcommon.Hash{} - - if !b.Valid { - return nil - } - - value, err := b.Value() - if err != nil { - return nil - } - s := value.(string) - - result.SetBytes([]byte(s)) - return &result -} - func byteArrayToHash(b []byte) gethcommon.Hash { result := gethcommon.Hash{} result.SetBytes(b) diff --git a/integration/manualtests/tx_test.go b/integration/manualtests/tx_test.go index 702167268d..9b91ae2678 100644 --- a/integration/manualtests/tx_test.go +++ b/integration/manualtests/tx_test.go @@ -2,10 +2,10 @@ package manualtests import ( "context" + "encoding/json" "errors" "fmt" "math/big" - "os" "strings" "testing" "time" @@ -21,6 +21,7 @@ import ( "github.com/obscuronet/go-obscuro/go/wallet" "github.com/obscuronet/go-obscuro/integration/datagenerator" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" gethcommon "github.com/ethereum/go-ethereum/common" gethlog "github.com/ethereum/go-ethereum/log" @@ -50,34 +51,32 @@ var ( 777, gethlog.New()) l2Host = "localhost" - l2Port = 37900 + l2Port = 43900 ) func TestL1IssueContractInteractWaitReceipt(t *testing.T) { - // test is skipped by default to avoid breaking CI - set env flag in `Run Configurations` to run it in IDE - if os.Getenv(_IDEFlag) == "" { - t.Skipf("set flag %s to run this test in the IDE", _IDEFlag) - } + t.Skipf("skip manual tests") + var err error ethClient, err := ethadapter.NewEthClient(l1Host, uint(l1Port), 30*time.Second, common.L2Address{}, gethlog.New()) - assert.Nil(t, err) + require.NoError(t, err) storeContractBytecode := "0x608060405234801561001057600080fd5b5061020b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b57806370ef6e0b14610059575b600080fd5b610043610075565b60405161005091906100ab565b60405180910390f35b610073600480360381019061006e9190610161565b61007e565b005b60008054905090565b836000819055508260008190555050505050565b6000819050919050565b6100a581610092565b82525050565b60006020820190506100c0600083018461009c565b92915050565b600080fd5b600080fd5b6100d981610092565b81146100e457600080fd5b50565b6000813590506100f6816100d0565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112610121576101206100fc565b5b8235905067ffffffffffffffff81111561013e5761013d610101565b5b60208301915083600182028301111561015a57610159610106565b5b9250929050565b6000806000806060858703121561017b5761017a6100c6565b5b6000610189878288016100e7565b945050602061019a878288016100e7565b935050604085013567ffffffffffffffff8111156101bb576101ba6100cb565b5b6101c78782880161010b565b92509250509295919450925056fea2646970667358221220eda68578fb741c32f26000b6c0273945f8322dd35f536c918e3d5a6193aaf62564736f6c63430008120033" nonce, err := ethClient.Nonce(l1Wallet.Address()) - assert.Nil(t, err) + require.NoError(t, err) l1Wallet.SetNonce(nonce) estimatedTx, err := ethClient.PrepareTransactionToSend(&types.LegacyTx{ Data: gethcommon.FromHex(storeContractBytecode), }, l1Wallet.Address(), l1Wallet.GetNonceAndIncrement()) - assert.Nil(t, err) + require.NoError(t, err) signedTx, err := l1Wallet.SignTransaction(estimatedTx) - assert.Nil(t, err) + require.NoError(t, err) err = ethClient.SendTransaction(signedTx) - assert.Nil(t, err) + require.NoError(t, err) fmt.Printf("Deployed Store Contract") fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) @@ -99,31 +98,28 @@ func TestL1IssueContractInteractWaitReceipt(t *testing.T) { } func TestL1IssueTxWaitReceipt(t *testing.T) { - // test is skipped by default to avoid breaking CI - set env flag in `Run Configurations` to run it in IDE - if os.Getenv(_IDEFlag) == "" { - t.Skipf("set flag %s to run this test in the IDE", _IDEFlag) - } + t.Skipf("skip manual tests") var err error ethClient, err := ethadapter.NewEthClient(l1Host, uint(l1Port), 30*time.Second, common.L2Address{}, gethlog.New()) - assert.Nil(t, err) + require.NoError(t, err) toAddr := datagenerator.RandomAddress() nonce, err := ethClient.Nonce(l1Wallet.Address()) - assert.Nil(t, err) + require.NoError(t, err) l1Wallet.SetNonce(nonce) estimatedTx, err := ethClient.PrepareTransactionToSend(&types.LegacyTx{ To: &toAddr, Value: big.NewInt(100), }, l1Wallet.Address(), l1Wallet.GetNonceAndIncrement()) - assert.Nil(t, err) + require.NoError(t, err) signedTx, err := l1Wallet.SignTransaction(estimatedTx) - assert.Nil(t, err) + require.NoError(t, err) err = ethClient.SendTransaction(signedTx) - assert.Nil(t, err) + require.NoError(t, err) fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) fmt.Printf("Checking for tx receipt for %s \n", signedTx.Hash()) @@ -144,21 +140,18 @@ func TestL1IssueTxWaitReceipt(t *testing.T) { } func TestL2IssueContractInteractWaitReceipt(t *testing.T) { - // test is skipped by default to avoid breaking CI - set env flag in `Run Configurations` to run it in IDE - if os.Getenv(_IDEFlag) == "" { - t.Skipf("set flag %s to run this test in the IDE", _IDEFlag) - } + t.Skipf("skip manual tests") ctx := context.Background() vk, err := viewingkey.GenerateViewingKeyForWallet(l2Wallet) - assert.Nil(t, err) + require.NoError(t, err) client, err := rpc.NewEncNetworkClient(fmt.Sprintf("ws://%s:%d", l2Host, l2Port), vk, gethlog.New()) - assert.Nil(t, err) + require.NoError(t, err) authClient := obsclient.NewAuthObsClient(client) balance, err := authClient.BalanceAt(context.Background(), nil) - assert.Nil(t, err) + require.NoError(t, err) if balance.Cmp(big.NewInt(0)) <= 0 { t.Errorf("not enough balance: has %s has %s obx", l2Wallet.Address().Hex(), balance.String()) @@ -166,7 +159,7 @@ func TestL2IssueContractInteractWaitReceipt(t *testing.T) { storeContractBytecode := "0x608060405234801561001057600080fd5b506101f3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100da565b60405180910390f35b610073600480360381019061006e9190610126565b61007e565b005b60008054905090565b806000819055507febfcf7c0a1b09f6499e519a8d8bb85ce33cd539ec6cbd964e116cd74943ead1a33826040516100b6929190610194565b60405180910390a150565b6000819050919050565b6100d4816100c1565b82525050565b60006020820190506100ef60008301846100cb565b92915050565b600080fd5b610103816100c1565b811461010e57600080fd5b50565b600081359050610120816100fa565b92915050565b60006020828403121561013c5761013b6100f5565b5b600061014a84828501610111565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017e82610153565b9050919050565b61018e81610173565b82525050565b60006040820190506101a96000830185610185565b6101b660208301846100cb565b939250505056fea264697066735822122071ae4262a5da0c5c7b417d9c6cd13b57b8fcfe79c9c526b96f482ee67ff3136c64736f6c63430008120033" nonce, err := authClient.NonceAt(ctx, nil) - assert.Nil(t, err) + require.NoError(t, err) l2Wallet.SetNonce(nonce) estimatedTx := authClient.EstimateGasAndGasPrice(&types.LegacyTx{ @@ -175,7 +168,7 @@ func TestL2IssueContractInteractWaitReceipt(t *testing.T) { GasPrice: gethcommon.Big1, Data: gethcommon.FromHex(storeContractBytecode), }) - assert.Nil(t, err) + require.NoError(t, err) contract, err := authClient.CallContract(ctx, ethereum.CallMsg{ From: l2Wallet.Address(), @@ -187,10 +180,10 @@ func TestL2IssueContractInteractWaitReceipt(t *testing.T) { } signedTx, err := l2Wallet.SignTransaction(estimatedTx) - assert.Nil(t, err) + require.NoError(t, err) err = authClient.SendTransaction(ctx, signedTx) - assert.Nil(t, err) + require.NoError(t, err) fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) fmt.Printf("Checking for tx receipt for %s \n", signedTx.Hash()) @@ -269,7 +262,7 @@ func TestL2IssueContractInteractWaitReceipt(t *testing.T) { ]` myAbi, err := abi.JSON(strings.NewReader(abiJSONString)) - assert.Nil(t, err) + require.NoError(t, err) pack, err := myAbi.Pack("store", big.NewInt(1)) if err != nil { @@ -283,13 +276,13 @@ func TestL2IssueContractInteractWaitReceipt(t *testing.T) { GasPrice: gethcommon.Big1, Data: pack, }) - assert.Nil(t, err) + require.NoError(t, err) signedTx, err = l2Wallet.SignTransaction(estimatedTx) - assert.Nil(t, err) + require.NoError(t, err) err = authClient.SendTransaction(ctx, signedTx) - assert.Nil(t, err) + require.NoError(t, err) fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) fmt.Printf("Checking for tx receipt for %s \n", signedTx.Hash()) @@ -320,21 +313,18 @@ func TestL2IssueContractInteractWaitReceipt(t *testing.T) { } func TestL2IssueTxWaitReceipt(t *testing.T) { - // test is skipped by default to avoid breaking CI - set env flag in `Run Configurations` to run it in IDE - if os.Getenv(_IDEFlag) == "" { - t.Skipf("set flag %s to run this test in the IDE", _IDEFlag) - } + t.Skipf("skip manual tests") ctx := context.Background() vk, err := viewingkey.GenerateViewingKeyForWallet(l2Wallet) - assert.Nil(t, err) + require.NoError(t, err) client, err := rpc.NewEncNetworkClient(fmt.Sprintf("ws://%s:%d", l2Host, l2Port), vk, gethlog.New()) - assert.Nil(t, err) + require.NoError(t, err) authClient := obsclient.NewAuthObsClient(client) balance, err := authClient.BalanceAt(context.Background(), nil) - assert.Nil(t, err) + require.NoError(t, err) if balance.Cmp(big.NewInt(0)) <= 0 { t.Errorf("not enough balance: has %s has %s obx", l2Wallet.Address().Hex(), balance.String()) @@ -342,7 +332,7 @@ func TestL2IssueTxWaitReceipt(t *testing.T) { toAddr := datagenerator.RandomAddress() nonce, err := authClient.NonceAt(ctx, nil) - assert.Nil(t, err) + require.NoError(t, err) l2Wallet.SetNonce(nonce) estimatedTx := authClient.EstimateGasAndGasPrice(&types.LegacyTx{ @@ -352,13 +342,78 @@ func TestL2IssueTxWaitReceipt(t *testing.T) { Gas: uint64(1_000_000), GasPrice: gethcommon.Big1, }) - assert.Nil(t, err) + require.NoError(t, err) + + signedTx, err := l2Wallet.SignTransaction(estimatedTx) + require.NoError(t, err) + + err = authClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) + fmt.Printf("Checking for tx receipt for %s \n", signedTx.Hash()) + var receipt *types.Receipt + for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(time.Second) { + receipt, err = authClient.TransactionReceipt(ctx, signedTx.Hash()) + if err == nil { + break + } + // + // Currently when a receipt is not available the obscuro node is returning nil instead of err ethereum.NotFound + // once that's fixed this commented block should be removed + //if !errors.Is(err, ethereum.NotFound) { + // t.Fatal(err) + //} + if receipt != nil && receipt.Status == 1 { + break + } + fmt.Printf("no tx receipt after %s - %s\n", time.Since(start), err) + } + + if receipt == nil { + t.Fatalf("Did not mine the transaction after %s seconds - receipt: %+v", 30*time.Second, receipt) + } + if receipt.Status == 0 { + t.Fatalf("Tx Failed") + } +} + +func TestL2IssueContractSubscribeChange(t *testing.T) { + t.Skipf("skip manual tests") + + ctx := context.Background() + + vk, err := viewingkey.GenerateViewingKeyForWallet(l2Wallet) + require.NoError(t, err) + client, err := rpc.NewEncNetworkClient(fmt.Sprintf("ws://%s:%d", l2Host, l2Port), vk, gethlog.New()) + require.NoError(t, err) + authClient := obsclient.NewAuthObsClient(client) + + balance, err := authClient.BalanceAt(context.Background(), nil) + require.NoError(t, err) + + if balance.Cmp(big.NewInt(0)) <= 0 { + t.Errorf("not enough balance: has %s has %s obx", l2Wallet.Address().Hex(), balance.String()) + } + + storeContractBytecode := "608060405234801561001057600080fd5b506101d7806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80630f2723ea14610030575b600080fd5b61004a60048036038101906100459190610137565b61004c565b005b8173ffffffffffffffffffffffffffffffffffffffff167fe86bd59ccd77aa1a9fbc46604e341e1dcc72f2a6e6637d5422736d645a71625e826040516100929190610186565b60405180910390a25050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100ce826100a3565b9050919050565b6100de816100c3565b81146100e957600080fd5b50565b6000813590506100fb816100d5565b92915050565b6000819050919050565b61011481610101565b811461011f57600080fd5b50565b6000813590506101318161010b565b92915050565b6000806040838503121561014e5761014d61009e565b5b600061015c858286016100ec565b925050602061016d85828601610122565b9150509250929050565b61018081610101565b82525050565b600060208201905061019b6000830184610177565b9291505056fea2646970667358221220d45d57b217a07cfd4ceecc8f5d2a9194a098e5fe1de98bc56c24cc400e21c96064736f6c63430008120033" + nonce, err := authClient.NonceAt(ctx, nil) + require.NoError(t, err) + + l2Wallet.SetNonce(nonce) + estimatedTx := authClient.EstimateGasAndGasPrice(&types.LegacyTx{ + Nonce: l2Wallet.GetNonceAndIncrement(), + Gas: uint64(1_000_000), + GasPrice: gethcommon.Big1, + Data: gethcommon.FromHex(storeContractBytecode), + }) + require.NoError(t, err) signedTx, err := l2Wallet.SignTransaction(estimatedTx) - assert.Nil(t, err) + require.NoError(t, err) err = authClient.SendTransaction(ctx, signedTx) - assert.Nil(t, err) + require.NoError(t, err) fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) fmt.Printf("Checking for tx receipt for %s \n", signedTx.Hash()) @@ -386,4 +441,97 @@ func TestL2IssueTxWaitReceipt(t *testing.T) { if receipt.Status == 0 { t.Fatalf("Tx Failed") } + + abiJSONString := `[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "IndexedAddressAndNumber", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "echo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +]` + + myAbi, err := abi.JSON(strings.NewReader(abiJSONString)) + require.NoError(t, err) + + pack, err := myAbi.Pack("echo", l2Wallet.Address(), big.NewInt(42)) + require.NoError(t, err) + + estimatedTx = authClient.EstimateGasAndGasPrice(&types.LegacyTx{ + Nonce: l2Wallet.GetNonceAndIncrement(), + To: &receipt.ContractAddress, + Gas: uint64(1_000_000), + GasPrice: gethcommon.Big1, + Data: pack, + }) + require.NoError(t, err) + + signedTx, err = l2Wallet.SignTransaction(estimatedTx) + require.NoError(t, err) + + err = authClient.SendTransaction(ctx, signedTx) + require.NoError(t, err) + + fmt.Printf("Created Tx: %s \n", signedTx.Hash().Hex()) + fmt.Printf("Checking for tx receipt for %s \n", signedTx.Hash()) + receipt = nil + for start := time.Now(); time.Since(start) < time.Minute; time.Sleep(time.Second) { + receipt, err = authClient.TransactionReceipt(ctx, signedTx.Hash()) + if err == nil { + break + } + // + // Currently when a receipt is not available the obscuro node is returning nil instead of err ethereum.NotFound + // once that's fixed this commented block should be removed + //if !errors.Is(err, ethereum.NotFound) { + // t.Fatal(err) + //} + if receipt != nil && receipt.Status == 1 { + break + } + fmt.Printf("no tx receipt after %s - %s\n", time.Since(start), err) + } + + if receipt == nil { + t.Fatalf("Did not mine the transaction after %s seconds - receipt: %+v", 30*time.Second, receipt) + } + if receipt.Status == 0 { + t.Fatalf("Tx Failed") + } + + result := json.RawMessage{} + err = client.Call(&result, "debug_eventLogRelevancy", signedTx.Hash()) + assert.NoError(t, err) + fmt.Println(err) } diff --git a/integration/obscuroscan/obscuroscan_test.go b/integration/obscuroscan/obscuroscan_test.go index 765bfd2ea6..4a518f01f5 100644 --- a/integration/obscuroscan/obscuroscan_test.go +++ b/integration/obscuroscan/obscuroscan_test.go @@ -47,7 +47,7 @@ const ( ) func TestObscuroscan(t *testing.T) { - t.Skip("Commented it out until more testing is driven from this test") + //t.Skip("Commented it out until more testing is driven from this test") startPort := integration.StartPortObscuroscanUnitTest createObscuroNetwork(t, startPort) @@ -178,6 +178,7 @@ func TestObscuroscan(t *testing.T) { 100, ) + fmt.Println("Running for 1 hour...") time.Sleep(time.Hour) // Gracefully shutdown err = obsScanContainer.Stop()