Skip to content

Commit

Permalink
fix: bootnode version RPC call (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
dimalinux authored May 9, 2023
1 parent 3859162 commit 0abc9e6
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 160 deletions.
30 changes: 18 additions & 12 deletions bootnode/bootnode.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"context"
"errors"
"fmt"
"math/big"
"net/http"

"github.com/athanorlabs/atomic-swap/common"
"github.com/athanorlabs/atomic-swap/net"
"github.com/athanorlabs/atomic-swap/rpc"

Expand All @@ -23,26 +23,27 @@ var log = logging.Logger("bootnode")

// Config provides the configuration for a bootnode.
type Config struct {
DataDir string
Bootnodes []string
HostListenIP string
Libp2pPort uint16
Libp2pKeyFile string
RPCPort uint16
EthereumChainID *big.Int
Env common.Environment
DataDir string
Bootnodes []string
HostListenIP string
Libp2pPort uint16
Libp2pKeyFile string
RPCPort uint16
}

// RunBootnode assembles and runs a bootnode instance, blocking until the node is
// shut down. Typically, shutdown happens because a signal handler cancels the
// passed in context, or when the shutdown RPC method is called.
func RunBootnode(ctx context.Context, cfg *Config) error {
chainID := common.ChainIDFromEnv(cfg.Env)
host, err := net.NewHost(&net.Config{
Ctx: ctx,
DataDir: cfg.DataDir,
Port: cfg.Libp2pPort,
KeyFile: cfg.Libp2pKeyFile,
Bootnodes: cfg.Bootnodes,
ProtocolID: fmt.Sprintf("%s/%d", net.ProtocolID, cfg.EthereumChainID.Int64()),
ProtocolID: fmt.Sprintf("%s/%d", net.ProtocolID, chainID),
ListenIP: cfg.HostListenIP,
IsRelayer: false,
IsBootnodeOnly: true,
Expand All @@ -61,9 +62,14 @@ func RunBootnode(ctx context.Context, cfg *Config) error {
}

rpcServer, err := rpc.NewServer(&rpc.Config{
Ctx: ctx,
Address: fmt.Sprintf("127.0.0.1:%d", cfg.RPCPort),
Net: host,
Ctx: ctx,
Env: cfg.Env,
Address: fmt.Sprintf("127.0.0.1:%d", cfg.RPCPort),
Net: host,
XMRTaker: nil,
XMRMaker: nil,
ProtocolBackend: nil,
RecoveryDB: nil,
Namespaces: map[string]struct{}{
rpc.DaemonNamespace: {},
rpc.NetNamespace: {},
Expand Down
14 changes: 7 additions & 7 deletions cmd/bootnode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,13 @@ func runBootnode(c *cli.Context) error {

rpcPort := uint16(c.Uint(flagRPCPort))
return bootnode.RunBootnode(c.Context, &bootnode.Config{
DataDir: config.DataDir,
Bootnodes: config.Bootnodes,
HostListenIP: hostListenIP,
Libp2pPort: libp2pPort,
Libp2pKeyFile: libp2pKeyFile,
RPCPort: rpcPort,
EthereumChainID: config.EthereumChainID,
Env: config.Env,
DataDir: config.DataDir,
Bootnodes: config.Bootnodes,
HostListenIP: hostListenIP,
Libp2pPort: libp2pPort,
Libp2pKeyFile: libp2pKeyFile,
RPCPort: rpcPort,
})
}

Expand Down
69 changes: 69 additions & 0 deletions cmd/bootnode/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2023 The AthanorLabs/atomic-swap Authors
// SPDX-License-Identifier: LGPL-3.0-only

package main

import (
"context"
"fmt"
"sync"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/athanorlabs/atomic-swap/cliutil"
"github.com/athanorlabs/atomic-swap/common"
"github.com/athanorlabs/atomic-swap/daemon"
"github.com/athanorlabs/atomic-swap/rpcclient"
)

func getFreePort(t *testing.T) uint16 {
port, err := common.GetFreeTCPPort()
require.NoError(t, err)
return uint16(port)
}

func TestBootnode(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
rpcPort := getFreePort(t)
dataDir := t.TempDir()

flags := []string{
"bootnode",
fmt.Sprintf("--%s=dev", flagEnv),
fmt.Sprintf("--%s=debug", cliutil.FlagLogLevel),
fmt.Sprintf("--%s=%s", flagDataDir, dataDir),
fmt.Sprintf("--%s=%d", flagRPCPort, rpcPort),
fmt.Sprintf("--%s=0", flagLibp2pPort),
}

var wg sync.WaitGroup
wg.Add(1)

go func() {
defer wg.Done()
err := cliApp().RunContext(ctx, flags)
// We may want to replace context.Cancelled with nil at some point in the code
assert.ErrorIs(t, context.Canceled, err)
}()

// Ensure the bootnode fully starts before some basic sanity checks
daemon.WaitForSwapdStart(t, rpcPort)

cli := rpcclient.NewClient(ctx, fmt.Sprintf("http://127.0.0.1:%d", rpcPort))
versionResp, err := cli.Version()
require.NoError(t, err)
require.NotEmpty(t, versionResp.P2PVersion)
t.Logf("Bootnode p2p version is: %s", versionResp.P2PVersion)
require.Nil(t, versionResp.SwapCreatorAddr) // bootnode does not know the address

addressResp, err := cli.Addresses()
require.NoError(t, err)
require.Greater(t, len(addressResp.Addrs), 1)

// We check the contract code below, but we don't need the daemon for that
cli.Shutdown()
wg.Wait()
}
36 changes: 1 addition & 35 deletions cmd/swapd/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,24 @@ import (
"context"
"crypto/ecdsa"
"fmt"
"os"
"path"
"path/filepath"
"time"

"github.com/athanorlabs/atomic-swap/common"
"github.com/athanorlabs/atomic-swap/common/vjson"
contracts "github.com/athanorlabs/atomic-swap/ethereum"
"github.com/athanorlabs/atomic-swap/ethereum/extethclient"

ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
)

const (
contractAddressesFile = "contract-addresses.json"
)

var (
errNoEthPrivateKey = fmt.Errorf("must provide --%s file for non-development environment", flagEthPrivKey)
)

type contractAddresses struct {
SwapCreatorAddr ethcommon.Address `json:"swapCreatorAddr" validate:"required"`
}

func getOrDeploySwapCreator(
ctx context.Context,
swapCreatorAddr ethcommon.Address,
env common.Environment,
dataDir string,
ec extethclient.EthClient,
) (ethcommon.Address, error) {
var err error
Expand All @@ -47,7 +34,7 @@ func getOrDeploySwapCreator(
time.Sleep(10 * time.Second)
}

swapCreatorAddr, err = deploySwapCreator(ctx, ec.Raw(), ec.PrivateKey(), dataDir)
swapCreatorAddr, err = deploySwapCreator(ctx, ec.Raw(), ec.PrivateKey())
if err != nil {
return ethcommon.Address{}, fmt.Errorf("failed to deploy swap creator: %w", err)
}
Expand All @@ -68,7 +55,6 @@ func deploySwapCreator(
ctx context.Context,
ec *ethclient.Client,
privkey *ecdsa.PrivateKey,
dataDir string,
) (ethcommon.Address, error) {
if privkey == nil {
return ethcommon.Address{}, errNoEthPrivateKey
Expand All @@ -79,25 +65,5 @@ func deploySwapCreator(
return ethcommon.Address{}, err
}

// store the contract addresses on disk
err = writeContractAddressesToFile(
path.Join(dataDir, contractAddressesFile),
&contractAddresses{
SwapCreatorAddr: swapCreatorAddr,
},
)
if err != nil {
return ethcommon.Address{}, fmt.Errorf("failed to write contract address to file: %w", err)
}

return swapCreatorAddr, nil
}

// writeContractAddressesToFile writes the contract addresses to the given file
func writeContractAddressesToFile(filePath string, addresses *contractAddresses) error {
jsonData, err := vjson.MarshalIndentStruct(addresses, "", " ")
if err != nil {
return err
}
return os.WriteFile(filepath.Clean(filePath), jsonData, 0600)
}
5 changes: 0 additions & 5 deletions cmd/swapd/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ import (
func TestGetOrDeploySwapCreator_Deploy(t *testing.T) {
pk := tests.GetTakerTestKey(t)
ec := extethclient.CreateTestClient(t, pk)
tmpDir := t.TempDir()

_, err := getOrDeploySwapCreator(
context.Background(),
ethcommon.Address{},
common.Development,
tmpDir,
ec,
)
require.NoError(t, err)
Expand All @@ -33,14 +31,12 @@ func TestGetOrDeploySwapCreator_Deploy(t *testing.T) {
func TestGetOrDeploySwapCreator_Get(t *testing.T) {
pk := tests.GetTakerTestKey(t)
ec := extethclient.CreateTestClient(t, pk)
tmpDir := t.TempDir()

// deploy and get address
address, err := getOrDeploySwapCreator(
context.Background(),
ethcommon.Address{},
common.Development,
tmpDir,
ec,
)
require.NoError(t, err)
Expand All @@ -49,7 +45,6 @@ func TestGetOrDeploySwapCreator_Get(t *testing.T) {
context.Background(),
address,
common.Development,
tmpDir,
ec,
)
require.NoError(t, err)
Expand Down
1 change: 0 additions & 1 deletion cmd/swapd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,6 @@ func validateOrDeployContracts(c *cli.Context, envConf *common.Config, ec exteth
c.Context,
envConf.SwapCreatorAddr,
envConf.Env,
envConf.DataDir,
ec,
)
if err != nil {
Expand Down
27 changes: 10 additions & 17 deletions cmd/swapd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package main

import (
"context"
"encoding/json"
"fmt"
"os"
"path"
Expand Down Expand Up @@ -78,30 +77,24 @@ func TestDaemon_DevXMRTaker(t *testing.T) {
assert.NoError(t, err)
}()

// Ensure the daemon fully started before we cancel the context
// Ensure the daemon fully before we query the contract address
daemon.WaitForSwapdStart(t, rpcPort)

cli := rpcclient.NewClient(ctx, fmt.Sprintf("http://127.0.0.1:%d", rpcPort))
versionResp, err := cli.Version()
require.NoError(t, err)

// We check the contract code below, but we don't need the daemon for that
cancel()
wg.Wait()

if t.Failed() {
return
}

//
// Validate that --deploy created a contract address file.
// At some future point, we will ask the RPC endpoint
// what the contract addresses are instead of using this file.
//
data, err := os.ReadFile(path.Join(dataDir, contractAddressesFile))
require.NoError(t, err)
m := make(map[string]string)
require.NoError(t, json.Unmarshal(data, &m))
swapCreatorAddr, ok := m["swapCreatorAddr"]
require.True(t, ok)

ec, _ := tests.NewEthClient(t)
ecCtx := context.Background()
err = contracts.CheckSwapCreatorContractCode(ecCtx, ec, ethcommon.HexToAddress(swapCreatorAddr))
err = contracts.CheckSwapCreatorContractCode(ecCtx, ec, *versionResp.SwapCreatorAddr)
require.NoError(t, err)
}

Expand All @@ -111,7 +104,7 @@ func TestDaemon_DevXMRMaker(t *testing.T) {
ec, _ := tests.NewEthClient(t)

// We tested --deploy with the taker, so test passing the contract address here
swapCreatorAddr, err := deploySwapCreator(context.Background(), ec, key, t.TempDir())
swapCreatorAddr, err := deploySwapCreator(context.Background(), ec, key)
require.NoError(t, err)

flags := []string{
Expand Down Expand Up @@ -148,7 +141,7 @@ func TestDaemon_BadFlags(t *testing.T) {
ec, _ := tests.NewEthClient(t)
ctx, _ := newTestContext(t)

swapCreatorAddr, err := deploySwapCreator(ctx, ec, key, t.TempDir())
swapCreatorAddr, err := deploySwapCreator(ctx, ec, key)
require.NoError(t, err)

baseFlags := []string{
Expand Down
Loading

0 comments on commit 0abc9e6

Please sign in to comment.