diff --git a/integration/manualtests/connection_test.go b/integration/manualtests/connection_test.go index d7ba3d5f6a..55f30e8f7c 100644 --- a/integration/manualtests/connection_test.go +++ b/integration/manualtests/connection_test.go @@ -2,23 +2,16 @@ package manualtests import ( "context" - "encoding/hex" "fmt" - "io" "log" - "net/http" - "strings" "testing" "github.com/ethereum/go-ethereum" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" - "github.com/obscuronet/go-obscuro/tools/walletextension/common" + "github.com/obscuronet/go-obscuro/tools/walletextension/lib" "github.com/stretchr/testify/require" - "github.com/valyala/fasthttp" - - gethcommon "github.com/ethereum/go-ethereum/common" ) func TestSubscribeToOG(t *testing.T) { @@ -29,21 +22,17 @@ func TestSubscribeToOG(t *testing.T) { ogWSAddress := "wss://dev-testnet.obscu.ro:81" // ogWSAddress := "ws://51.132.131.47:81" - // join the network - statusCode, userID, err := fasthttp.Get(nil, fmt.Sprintf("%s/v1/join/", ogHTTPAddress)) - require.NoError(t, err) // dialing to the given TCP address timed out - fmt.Println(statusCode) - fmt.Println(userID) + ogClient := lib.NewObscuroGatewayLibrary(ogHTTPAddress, ogWSAddress) - // sign the message - messagePayload := signMessage(string(userID)) + // join the network + err := ogClient.Join() + require.NoError(t, err) + fmt.Println(ogClient.UserID()) // register an account - var regAccountResp []byte - regAccountResp, err = registerAccount(ogHTTPAddress, string(userID), messagePayload) + err = ogClient.RegisterAccount(l2Wallet.PrivateKey(), l2Wallet.Address()) require.NoError(t, err) - fmt.Println(string(regAccountResp)) - fmt.Println(hex.EncodeToString(regAccountResp)) + fmt.Println("Registered account: ", l2Wallet.Address().Hex()) // Using WS -> @@ -81,49 +70,3 @@ func TestSubscribeToOG(t *testing.T) { } } } - -func registerAccount(baseAddress, userID, payload string) ([]byte, error) { - req, err := http.NewRequestWithContext( - context.Background(), - http.MethodPost, - baseAddress+"/v1/authenticate/?u="+userID, - strings.NewReader(payload), - ) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/json; charset=UTF-8") - - client := &http.Client{} - response, err := client.Do(req) - if err != nil { - return nil, err - } - - defer response.Body.Close() - return io.ReadAll(response.Body) -} - -// { -// "signature": "0xc784adea83ed3ec60528f4747418c85abe553b35a47fd2c95425de654bb9d0d40ede24aec182e6a2ec65c0c7c6aedab7823f21a9b9f7ff5db3a77a9f90dc97b41c", -// "message": "Register e097c4a10d4285d13b377985834b4c57e069b5856cc6c2cd4a038f62da4bc459 for 0x06ed49a32fcc5094abee51a4ffd46dd23b62a191" -// } -func signMessage(userID string) string { - pk := l2Wallet.PrivateKey() - address := l2Wallet.Address() - hexAddress := address.Hex() - - message := fmt.Sprintf("Register %s for %s", userID, strings.ToLower(hexAddress)) - prefixedMessage := fmt.Sprintf(common.PersonalSignMessagePrefix, len(message), message) - - messageHash := crypto.Keccak256([]byte(prefixedMessage)) - sig, err := crypto.Sign(messageHash, pk) - if err != nil { - log.Fatalf("Failed to sign message: %v", err) - } - sig[64] += 27 - signature := "0x" + hex.EncodeToString(sig) - payload := fmt.Sprintf("{\"signature\": \"%s\", \"message\": \"%s\"}", signature, message) - fmt.Println(payload) - return payload -} diff --git a/integration/obscurogateway/obscurogateway_test.go b/integration/obscurogateway/obscurogateway_test.go index 02d1967878..f6cd9e3862 100644 --- a/integration/obscurogateway/obscurogateway_test.go +++ b/integration/obscurogateway/obscurogateway_test.go @@ -9,16 +9,11 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - "github.com/valyala/fasthttp" - gethcommon "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/obscuronet/go-obscuro/go/common" - "github.com/obscuronet/go-obscuro/go/common/viewingkey" - "github.com/obscuronet/go-obscuro/go/obsclient" - "github.com/obscuronet/go-obscuro/go/rpc" "github.com/obscuronet/go-obscuro/go/wallet" "github.com/obscuronet/go-obscuro/integration" "github.com/obscuronet/go-obscuro/integration/common/testlog" @@ -28,7 +23,10 @@ import ( "github.com/obscuronet/go-obscuro/integration/simulation/params" "github.com/obscuronet/go-obscuro/tools/walletextension/config" "github.com/obscuronet/go-obscuro/tools/walletextension/container" + "github.com/obscuronet/go-obscuro/tools/walletextension/lib" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/valyala/fasthttp" ) func init() { //nolint:gochecknoinits @@ -45,7 +43,6 @@ const ( ) func TestObscuroGateway(t *testing.T) { - t.Skip("Commented it out until more testing is driven from this test") startPort := integration.StartPortObscuroGatewayUnitTest wallets := createObscuroNetwork(t, startPort) @@ -57,6 +54,7 @@ func TestObscuroGateway(t *testing.T) { NodeRPCWebsocketAddress: fmt.Sprintf("127.0.0.1:%d", startPort+integration.DefaultHostRPCWSOffset), LogPath: "sys_out", VerboseFlag: false, + DBType: "sqlite", } obscuroGwContainer := container.NewWalletExtensionContainerFromConfig(obscuroGatewayConf, testlog.Logger()) @@ -71,52 +69,56 @@ func TestObscuroGateway(t *testing.T) { time.Sleep(5 * time.Second) // make sure the server is ready to receive requests - serverAddress := fmt.Sprintf("http://%s:%d", obscuroGatewayConf.WalletExtensionHost, obscuroGatewayConf.WalletExtensionPortHTTP) + httpURL := fmt.Sprintf("http://%s:%d", obscuroGatewayConf.WalletExtensionHost, obscuroGatewayConf.WalletExtensionPortHTTP) + wsURL := fmt.Sprintf("ws://%s:%d", obscuroGatewayConf.WalletExtensionHost, obscuroGatewayConf.WalletExtensionPortWS) // make sure the server is ready to receive requests - err := waitServerIsReady(serverAddress) + err := waitServerIsReady(httpURL) require.NoError(t, err) - w := wallets.L2FaucetWallet + // join + register against the og + ogClient := lib.NewObscuroGatewayLibrary(httpURL, wsURL) + err = ogClient.Join() + require.NoError(t, err) - vk, err := viewingkey.GenerateViewingKeyForWallet(w) - assert.Nil(t, err) - client, err := rpc.NewEncNetworkClient(fmt.Sprintf("ws://%s", obscuroGatewayConf.NodeRPCWebsocketAddress), vk, testlog.Logger()) - assert.Nil(t, err) - authClient := obsclient.NewAuthObsClient(client) + w := wallets.L2FaucetWallet + err = ogClient.RegisterAccount(w.PrivateKey(), w.Address()) + require.NoError(t, err) - balance, err := authClient.BalanceAt(context.Background(), nil) - assert.Nil(t, err) - assert.NotEqual(t, big.NewInt(0), balance) + // use a standard eth client via the og + ethStdClient, err := ethclient.Dial(ogClient.HTTP()) + require.NoError(t, err) - txHash := transferRandomAddr(t, authClient, w) + // check the balance + balance, err := ethStdClient.BalanceAt(context.Background(), w.Address(), nil) + require.NoError(t, err) + require.True(t, big.NewInt(0).Cmp(balance) == -1) - addr := w.Address() - receipts, err := authClient.GetReceiptsByAddress(context.Background(), &addr) + // issue a tx and check it was successfully minted + txHash := transferRandomAddr(t, ethStdClient, w) + receipt, err := ethStdClient.TransactionReceipt(context.Background(), txHash) assert.NoError(t, err) - - assert.Equal(t, 1, len(receipts)) - assert.Equal(t, txHash.Hex(), receipts[0].TxHash.Hex()) + require.True(t, receipt.Status == 1) // Gracefully shutdown err = obscuroGwContainer.Stop() assert.NoError(t, err) } -func transferRandomAddr(t *testing.T, authClient *obsclient.AuthObsClient, w wallet.Wallet) common.TxHash { +func transferRandomAddr(t *testing.T, client *ethclient.Client, w wallet.Wallet) common.TxHash { ctx := context.Background() toAddr := datagenerator.RandomAddress() - nonce, err := authClient.NonceAt(ctx, nil) + nonce, err := client.NonceAt(ctx, w.Address(), nil) assert.Nil(t, err) w.SetNonce(nonce) - estimatedTx := authClient.EstimateGasAndGasPrice(&types.LegacyTx{ + estimatedTx := &types.LegacyTx{ Nonce: w.GetNonceAndIncrement(), To: &toAddr, Value: big.NewInt(100), Gas: uint64(1_000_000), GasPrice: gethcommon.Big1, - }) + } assert.Nil(t, err) fmt.Println("Transferring from:", w.Address(), " to:", toAddr) @@ -124,14 +126,14 @@ func transferRandomAddr(t *testing.T, authClient *obsclient.AuthObsClient, w wal signedTx, err := w.SignTransaction(estimatedTx) assert.Nil(t, err) - err = authClient.SendTransaction(ctx, signedTx) + err = client.SendTransaction(ctx, signedTx) assert.Nil(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()) + receipt, err = client.TransactionReceipt(ctx, signedTx.Hash()) if err == nil { break } @@ -169,6 +171,7 @@ func createObscuroNetwork(t *testing.T, startPort int) *params.SimWallets { ERC20ContractLib: ethereummock.NewERC20ContractLibMock(), Wallets: wallets, StartPort: startPort, + WithPrefunding: true, } obscuroNetwork := network.NewNetworkOfSocketNodes(wallets) diff --git a/tools/walletextension/lib/README.md b/tools/walletextension/lib/README.md new file mode 100644 index 0000000000..313078399a --- /dev/null +++ b/tools/walletextension/lib/README.md @@ -0,0 +1 @@ +A golang based library to use the obscuro gateway programmatically. \ No newline at end of file diff --git a/tools/walletextension/lib/client_lib.go b/tools/walletextension/lib/client_lib.go new file mode 100644 index 0000000000..e6bccea96a --- /dev/null +++ b/tools/walletextension/lib/client_lib.go @@ -0,0 +1,92 @@ +package lib + +import ( + "context" + "crypto/ecdsa" + "encoding/hex" + "fmt" + "io" + "net/http" + "strings" + + gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/obscuronet/go-obscuro/tools/walletextension/common" + "github.com/valyala/fasthttp" +) + +type OGLib struct { + httpURL string + wsURL string + userID []byte +} + +func NewObscuroGatewayLibrary(httpURL, wsURL string) *OGLib { + return &OGLib{ + httpURL: httpURL, + wsURL: wsURL, + } +} + +func (o *OGLib) UserID() string { + return string(o.userID) +} + +func (o *OGLib) Join() error { + // todo move this to stdlib + statusCode, userID, err := fasthttp.Get(nil, fmt.Sprintf("%s/v1/join/", o.httpURL)) + if err != nil || statusCode != 200 { + return fmt.Errorf(fmt.Sprintf("Failed to get userID. Status code: %d, err: %s", statusCode, err)) + } + o.userID = userID + return nil +} + +func (o *OGLib) RegisterAccount(pk *ecdsa.PrivateKey, addr gethcommon.Address) error { + // create the registration message + message := fmt.Sprintf("Register %s for %s", o.userID, strings.ToLower(addr.Hex())) + prefixedMessage := fmt.Sprintf(common.PersonalSignMessagePrefix, len(message), message) + + messageHash := crypto.Keccak256([]byte(prefixedMessage)) + sig, err := crypto.Sign(messageHash, pk) + if err != nil { + return fmt.Errorf("failed to sign message: %w", err) + } + sig[64] += 27 + signature := "0x" + hex.EncodeToString(sig) + payload := fmt.Sprintf("{\"signature\": \"%s\", \"message\": \"%s\"}", signature, message) + + // issue the registration message + req, err := http.NewRequestWithContext( + context.Background(), + http.MethodPost, + o.httpURL+"/v1/authenticate/?u="+string(o.userID), + strings.NewReader(payload), + ) + if err != nil { + return fmt.Errorf("unable to create request - %w", err) + } + + req.Header.Set("Content-Type", "application/json; charset=UTF-8") + + client := &http.Client{} + response, err := client.Do(req) + if err != nil { + return fmt.Errorf("unable to issue request - %w", err) + } + + defer response.Body.Close() + _, err = io.ReadAll(response.Body) + if err != nil { + return fmt.Errorf("unable to read response - %w", err) + } + return nil +} + +func (o *OGLib) HTTP() string { + return fmt.Sprintf("%s/v1/?u=%s", o.httpURL, o.userID) +} + +func (o *OGLib) WS() string { + return fmt.Sprintf("%s/v1/?u=%s", o.wsURL, o.userID) +}