Skip to content

Commit

Permalink
Library for obscuro gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
otherview committed Oct 11, 2023
1 parent 5405c3f commit 4c48d57
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 96 deletions.
75 changes: 9 additions & 66 deletions integration/manualtests/connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 ->

Expand Down Expand Up @@ -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
}
63 changes: 33 additions & 30 deletions integration/obscurogateway/obscurogateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand All @@ -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)

Expand All @@ -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())
Expand All @@ -71,67 +69,71 @@ 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)

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
}
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions tools/walletextension/lib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A golang based library to use the obscuro gateway programmatically.
92 changes: 92 additions & 0 deletions tools/walletextension/lib/client_lib.go
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 4c48d57

Please sign in to comment.