Test cleanup (#135)

* version independent monerod path with localhost-only binding

* fixed lint target and install script

* created 3rd ETH key constant to avoid race condition in tests

* updated run-integration-tests.sh with the same changes made to run-unit-tests.sh

* new design for paritioning out 2 unique keys to test packages

* restored accidentally deleted tests/alice.key

* removed websocket connection leaks from tests

* made file paths unique between tests with better file cleanup

* fix for the websocket connection leak commit

* reverted increase of GenerateBlocks (didn't mean to commit that)

* fixed maker/taker key that I had reversed

* fixed incorrect zero-balance check

* fixed comment on ClaimOrRefund

* added back sample script for installing go in /usr/local/go

* etchclient creation cleanup using t.Cleanup()

* minor cleanup to ganache_test_keys code

* initial dynamic monero-wallet-rpc implementation for tests

* converted monero tests to use dynamic monero-wallet-rpc services

* unit tests all using dynamic monero-wallet-rpc services

* fixed 2 tests that failed after moving to dynamic monero-wallet-rpc services

* fixed low balance issues in TestSwapState_NotifyClaimed

Co-authored-by: noot <36753753+noot@users.noreply.github.com>
This commit is contained in:
Dmitry Holodov
2022-06-29 12:36:03 -05:00
committed by GitHub
parent 68f17665af
commit adfb0fa602
46 changed files with 518 additions and 243 deletions

6
.gitignore vendored
View File

@@ -11,8 +11,8 @@
*.dylib *.dylib
# Monero dir # Monero dir
monero.tar.bz2 /monero.tar.bz2
/monero-x86* /monero-*
# bin # bin
swapcli swapcli
@@ -52,4 +52,4 @@ Cargo.lock
*.key *.key
log log
*.log *.log

View File

@@ -1,8 +1,10 @@
.PHONY: lint test install build build-dleq mock .PHONY: lint test install build build-dleq mock
all: build-dleq install all: build-dleq install
GOPATH ?= $(shell go env GOPATH)
lint: lint:
./scripts/install_lint.sh ./scripts/install-lint.sh
${GOPATH}/bin/golangci-lint run ${GOPATH}/bin/golangci-lint run
test: test:

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"path"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
pcommon "github.com/noot/atomic-swap/protocol" pcommon "github.com/noot/atomic-swap/protocol"
@@ -20,7 +21,7 @@ var (
errNoEthereumPrivateKey = errors.New("must provide --ethereum-privkey file for non-development environment") errNoEthereumPrivateKey = errors.New("must provide --ethereum-privkey file for non-development environment")
) )
func getOrDeploySwapFactory(address ethcommon.Address, env common.Environment, basepath string, chainID *big.Int, func getOrDeploySwapFactory(address ethcommon.Address, env common.Environment, basePath string, chainID *big.Int,
privkey *ecdsa.PrivateKey, ec *ethclient.Client) (*swapfactory.SwapFactory, ethcommon.Address, error) { privkey *ecdsa.PrivateKey, ec *ethclient.Client) (*swapfactory.SwapFactory, ethcommon.Address, error) {
var ( var (
sf *swapfactory.SwapFactory sf *swapfactory.SwapFactory
@@ -46,7 +47,7 @@ func getOrDeploySwapFactory(address ethcommon.Address, env common.Environment, b
log.Infof("deployed SwapFactory.sol: address=%s tx hash=%s", address, tx.Hash()) log.Infof("deployed SwapFactory.sol: address=%s tx hash=%s", address, tx.Hash())
// store the contract address on disk // store the contract address on disk
fp := fmt.Sprintf("%s/contractaddress", basepath) fp := path.Join(basePath, "contractaddress")
if err = pcommon.WriteContractAddressToFile(fp, address.String()); err != nil { if err = pcommon.WriteContractAddressToFile(fp, address.String()); err != nil {
return nil, ethcommon.Address{}, fmt.Errorf("failed to write contract address to file: %w", err) return nil, ethcommon.Address{}, fmt.Errorf("failed to write contract address to file: %w", err)
} }

View File

@@ -5,6 +5,7 @@ import (
"testing" "testing"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/tests"
ethcommon "github.com/ethereum/go-ethereum/common" ethcommon "github.com/ethereum/go-ethereum/common"
ethcrypto "github.com/ethereum/go-ethereum/crypto" ethcrypto "github.com/ethereum/go-ethereum/crypto"
@@ -13,15 +14,18 @@ import (
) )
func TestGetOrDeploySwapFactory(t *testing.T) { func TestGetOrDeploySwapFactory(t *testing.T) {
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRTaker) pk, err := ethcrypto.HexToECDSA(tests.GetTakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
defer ec.Close()
tmpDir := t.TempDir()
_, addr, err := getOrDeploySwapFactory(ethcommon.Address{}, _, addr, err := getOrDeploySwapFactory(ethcommon.Address{},
common.Development, common.Development,
"/tmp", tmpDir,
big.NewInt(common.GanacheChainID), big.NewInt(common.GanacheChainID),
pk, pk,
ec, ec,
@@ -31,7 +35,7 @@ func TestGetOrDeploySwapFactory(t *testing.T) {
_, addr2, err := getOrDeploySwapFactory(addr, _, addr2, err := getOrDeploySwapFactory(addr,
common.Development, common.Development,
"/tmp", tmpDir,
big.NewInt(common.GanacheChainID), big.NewInt(common.GanacheChainID),
pk, pk,
ec, ec,

View File

@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"strconv" "strconv"
"testing" "testing"
@@ -16,6 +17,7 @@ import (
"github.com/noot/atomic-swap/protocol/xmrmaker" "github.com/noot/atomic-swap/protocol/xmrmaker"
"github.com/noot/atomic-swap/protocol/xmrtaker" "github.com/noot/atomic-swap/protocol/xmrtaker"
"github.com/noot/atomic-swap/swapfactory" "github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/urfave/cli" "github.com/urfave/cli"
@@ -120,7 +122,7 @@ func createInfoFile(t *testing.T, kpA, kpB *mcrypto.PrivateKeyPair, contractAddr
bz, err := json.MarshalIndent(infofile, "", "\t") bz, err := json.MarshalIndent(infofile, "", "\t")
require.NoError(t, err) require.NoError(t, err)
filepath := os.TempDir() + "/test-infofile.txt" filepath := path.Join(t.TempDir(), "test-infofile.txt")
err = ioutil.WriteFile(filepath, bz, os.ModePerm) err = ioutil.WriteFile(filepath, bz, os.ModePerm)
require.NoError(t, err) require.NoError(t, err)
return filepath return filepath
@@ -136,10 +138,11 @@ func TestRecover_sharedSwapSecret(t *testing.T) {
c := newTestContext(t, c := newTestContext(t,
"test --xmrtaker with shared swap secret", "test --xmrtaker with shared swap secret",
[]string{flagXMRTaker, flagInfoFile}, []string{flagXMRTaker, flagInfoFile, flagMoneroWalletEndpoint},
[]interface{}{ []interface{}{
true, true,
infoFilePath, infoFilePath,
tests.CreateWalletRPCService(t),
}, },
) )

View File

@@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/urfave/cli" "github.com/urfave/cli"
@@ -28,19 +29,14 @@ var (
// GetEthereumPrivateKey returns an ethereum private key hex string given the CLI options. // GetEthereumPrivateKey returns an ethereum private key hex string given the CLI options.
func GetEthereumPrivateKey(c *cli.Context, env common.Environment, devXMRMaker, func GetEthereumPrivateKey(c *cli.Context, env common.Environment, devXMRMaker,
useExternal bool) (ethPrivKey string, err error) { useExternal bool) (ethPrivKeyHex string, err error) {
if c.String(flagEthereumPrivKey) != "" { if c.String(flagEthereumPrivKey) != "" {
ethPrivKeyFile := c.String(flagEthereumPrivKey) ethPrivKeyFile := c.String(flagEthereumPrivKey)
key, err := os.ReadFile(filepath.Clean(ethPrivKeyFile)) key, err := os.ReadFile(filepath.Clean(ethPrivKeyFile))
if err != nil { if err != nil {
return "", fmt.Errorf("failed to read ethereum-privkey file: %w", err) return "", fmt.Errorf("failed to read ethereum-privkey file: %w", err)
} }
ethPrivKeyHex = strings.TrimSpace(string(key))
if key[len(key)-1] == '\n' {
key = key[:len(key)-1]
}
ethPrivKey = string(key)
} else { } else {
if env != common.Development || useExternal { if env != common.Development || useExternal {
// TODO: allow this to be set via RPC // TODO: allow this to be set via RPC
@@ -50,13 +46,13 @@ func GetEthereumPrivateKey(c *cli.Context, env common.Environment, devXMRMaker,
log.Warn("no ethereum private key file provided, using ganache deterministic key") log.Warn("no ethereum private key file provided, using ganache deterministic key")
if devXMRMaker { if devXMRMaker {
ethPrivKey = common.DefaultPrivKeyXMRMaker ethPrivKeyHex = common.DefaultPrivKeyXMRMaker
} else { } else {
ethPrivKey = common.DefaultPrivKeyXMRTaker ethPrivKeyHex = common.DefaultPrivKeyXMRTaker
} }
} }
return ethPrivKey, nil return ethPrivKeyHex, nil
} }
// GetEnvironment returns a common.Environment from the CLI options. // GetEnvironment returns a common.Environment from the CLI options.

View File

@@ -10,9 +10,9 @@ const (
DefaultMoneroDaemonEndpoint = "http://127.0.0.1:18081/json_rpc" DefaultMoneroDaemonEndpoint = "http://127.0.0.1:18081/json_rpc"
DefaultEthEndpoint = "ws://localhost:8545" DefaultEthEndpoint = "ws://localhost:8545"
// DefaultPrivKeyXMRTaker is the private key at index 0 from `ganache-cli -d` // DefaultPrivKeyXMRTaker is the private key at index 0 from `ganache-cli --deterministic`
DefaultPrivKeyXMRTaker = "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d" DefaultPrivKeyXMRTaker = "4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d"
// DefaultPrivKeyXMRMaker is the private key at index 1 from `ganache-cli -d` // DefaultPrivKeyXMRMaker is the private key at index 1 from `ganache-cli --deterministic`
DefaultPrivKeyXMRMaker = "6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1" DefaultPrivKeyXMRMaker = "6cbed15c793ce57650b9877cf6fa156fbef513c4e6134f022a85b1ffdd59b2a1"
) )

View File

@@ -90,7 +90,7 @@ type FarcasterDLEq struct{}
// Prove generates a new DLEq proof // Prove generates a new DLEq proof
func (d *FarcasterDLEq) Prove() (*Proof, error) { func (d *FarcasterDLEq) Prove() (*Proof, error) {
t := time.Now().Format("2006-Jan-2-15:04:05") t := time.Now().Format("2006-01-02-15:04:05.999999999")
path := fmt.Sprintf("%s-%s", defaultProofPath, t) path := fmt.Sprintf("%s-%s", defaultProofPath, t)
cmd := exec.Command(dleqGenBinPath, path) cmd := exec.Command(dleqGenBinPath, path)
@@ -119,7 +119,7 @@ func (d *FarcasterDLEq) Prove() (*Proof, error) {
// Verify verifies a DLEq proof // Verify verifies a DLEq proof
func (d *FarcasterDLEq) Verify(p *Proof) (*VerifyResult, error) { func (d *FarcasterDLEq) Verify(p *Proof) (*VerifyResult, error) {
t := time.Now().Format("2006-Jan-2-15:04:05") t := time.Now().Format("2006-01-02-15:04:05.999999999")
path := fmt.Sprintf("%s-verify-%s", defaultProofPath, t) path := fmt.Sprintf("%s-verify-%s", defaultProofPath, t)
if err := ioutil.WriteFile(path, p.proof, os.ModePerm); err != nil { if err := ioutil.WriteFile(path, p.proof, os.ModePerm); err != nil {

View File

@@ -1,11 +1,17 @@
# Building the project # Building the project
1. Install go [here](https://go.dev/doc/install). 1. Install Golang
For Linux 64-bit: On Ubuntu, the easiest way to keep up-to-date with the latest stable version of
Go is with snap:
```bash ```bash
wget https://go.dev/dl/go1.18.linux-amd64.tar.gz sudo snap install go --classic
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.18.linux-amd64.tar.gz ```
On other systems or in docker, use the directions here: https://go.dev/doc/install.
Summary for X86-64 Linux:
```bash
wget https://go.dev/dl/go1.18.3.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz
echo "export PATH=$PATH:/usr/local/go/bin" >> .profile echo "export PATH=$PATH:/usr/local/go/bin" >> .profile
source .profile source .profile
``` ```
@@ -21,4 +27,4 @@ cd atomic-swap
make build make build
``` ```
This creates the binaries `swapd` and `swapcli`. This creates the binaries `swapd` and `swapcli`.

View File

@@ -3,23 +3,29 @@
### Requirements ### Requirements
- go 1.17+ (see [build instructions](./build.md) to download Go.) - go 1.17+ (see [build instructions](./build.md) to download Go.)
- ganache-cli (can be installed with `npm i -g ganache-cli`) I suggest using nvm to install npm: https://github.com/nvm-sh/nvm#installing-and-updating - ganache (can be installed with `npm install --location=global ganache-cli`)
Note: this program has only been tested on Ubuntu 20.04. These programs and scripts have only been tested on X86-64 Ubuntu 20.04 and 22.04.
Using nvm is [the suggested way](https://github.com/nvm-sh/nvm#installing-and-updating)
to install npm. If you install npm using a package manager like snap, ensure the install
prefix (`npm config get prefix`) is a directory that you have write access to without sudo.
You can change the directory with the command `npm config set prefix ~/.npm-packages`. See
[this document](https://github.com/sindresorhus/guides/blob/main/npm-global-without-sudo.md)
if you want a more sophisticated setup.
#### Set up development environment #### Set up development environment
Note: the `scripts/install-monero-linux.sh` script will download the monero binaries needed for you. You can also check out the `scripts/run-unit-tests.sh` script for the commands needed to setup the environment. Note: the `scripts/install-monero-linux.sh` script will download the monero binaries needed for you. You can also check out the `scripts/run-unit-tests.sh` script for the commands needed to setup the environment.
Start ganache-cli with determinstic keys: Start ganache-cli with deterministic keys:
```bash ```bash
ganache-cli -d ganache-cli --deterministic --accounts=20
``` ```
Start monerod for regtest, this binary is in the monero bin directory: Start monerod for regtest, this binary is in the monero bin directory:
```bash ```bash
cd ./monero-x86_64-linux-gnu cd ./monero-bin
./monerod --regtest --fixed-difficulty=1 --rpc-bind-port 18081 --offline ./monerod --regtest --fixed-difficulty=1 --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18081 --offline
``` ```
Create a wallet for "Bob", who will own XMR later on: Create a wallet for "Bob", who will own XMR later on:
@@ -31,7 +37,7 @@ You do not need to mine blocks, and you can exit the the wallet-cli once Bob's a
Start monero-wallet-rpc for Bob on port 18083. Make sure `--wallet-dir` corresponds to the directory the wallet from the previous step is in: Start monero-wallet-rpc for Bob on port 18083. Make sure `--wallet-dir` corresponds to the directory the wallet from the previous step is in:
```bash ```bash
./monero-wallet-rpc --rpc-bind-port 18083 --password "" --disable-rpc-login --wallet-dir . ./monero-wallet-rpc --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18083 --password "" --disable-rpc-login --wallet-dir .
``` ```
Open the wallet: Open the wallet:
@@ -61,7 +67,7 @@ This will deposit some XMR in Bob's account.
Start monero-wallet-rpc for Alice on port 18084 (note that the directory provided to `--wallet-dir` is where Alice's XMR wallet will end up): Start monero-wallet-rpc for Alice on port 18084 (note that the directory provided to `--wallet-dir` is where Alice's XMR wallet will end up):
```bash ```bash
./monero-wallet-rpc --rpc-bind-port 18084 --password "" --disable-rpc-login --wallet-dir . ./monero-wallet-rpc --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18084 --password "" --disable-rpc-login --wallet-dir .
``` ```
#### Build and run #### Build and run

View File

@@ -1,14 +1,13 @@
package monero package monero
import ( import (
"crypto/rand"
"fmt" "fmt"
"math/big"
"testing" "testing"
"time" "time"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
mcrypto "github.com/noot/atomic-swap/crypto/monero" mcrypto "github.com/noot/atomic-swap/crypto/monero"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -19,16 +18,16 @@ func TestClient_Transfer(t *testing.T) {
} }
const amount = 2800000000 const amount = 2800000000
cXMRMaker := NewClient(common.DefaultXMRMakerMoneroEndpoint) cXMRMaker := NewClient(tests.CreateWalletRPCService(t))
err := cXMRMaker.OpenWallet("test-wallet", "") err := cXMRMaker.CreateWallet("test-wallet", "")
require.NoError(t, err) require.NoError(t, err)
xmrmakerAddr, err := cXMRMaker.callGetAddress(0) xmrmakerAddr, err := cXMRMaker.callGetAddress(0)
require.NoError(t, err) require.NoError(t, err)
daemon := NewClient(common.DefaultMoneroDaemonEndpoint) daemon := NewClient(common.DefaultMoneroDaemonEndpoint)
_ = daemon.callGenerateBlocks(xmrmakerAddr.Address, 181) _ = daemon.callGenerateBlocks(xmrmakerAddr.Address, 512)
time.Sleep(time.Second * 10) time.Sleep(time.Second * 10)
@@ -51,13 +50,10 @@ func TestClient_Transfer(t *testing.T) {
kpABPub := mcrypto.SumSpendAndViewKeys(kpA.PublicKeyPair(), kpB.PublicKeyPair()) kpABPub := mcrypto.SumSpendAndViewKeys(kpA.PublicKeyPair(), kpB.PublicKeyPair())
vkABPriv := mcrypto.SumPrivateViewKeys(kpA.ViewKey(), kpB.ViewKey()) vkABPriv := mcrypto.SumPrivateViewKeys(kpA.ViewKey(), kpB.ViewKey())
r, err := rand.Int(rand.Reader, big.NewInt(10000)) cXMRTaker := NewClient(tests.CreateWalletRPCService(t))
require.NoError(t, err)
cXMRTaker := NewClient(common.DefaultXMRTakerMoneroEndpoint)
// generate view-only account for A+B // generate view-only account for A+B
walletFP := fmt.Sprintf("test-wallet-%d", r) walletFP := fmt.Sprintf("test-wallet-%s", time.Now().Format("2006-01-02-15:04:05.999999999"))
err = cXMRTaker.callGenerateFromKeys(nil, vkABPriv, kpABPub.Address(common.Mainnet), walletFP, "") err = cXMRTaker.callGenerateFromKeys(nil, vkABPriv, kpABPub.Address(common.Mainnet), walletFP, "")
require.NoError(t, err) require.NoError(t, err)
err = cXMRTaker.OpenWallet(walletFP, "") err = cXMRTaker.OpenWallet(walletFP, "")
@@ -84,20 +80,20 @@ func TestClient_Transfer(t *testing.T) {
time.Sleep(time.Second) time.Sleep(time.Second)
} }
_ = daemon.callGenerateBlocks(xmrmakerAddr.Address, 16) err = daemon.callGenerateBlocks(xmrmakerAddr.Address, 16)
require.NoError(t, err)
// generate spend account for A+B // generate spend account for A+B
skAKPriv := mcrypto.SumPrivateSpendKeys(kpA.SpendKey(), kpB.SpendKey()) skAKPriv := mcrypto.SumPrivateSpendKeys(kpA.SpendKey(), kpB.SpendKey())
// ignore the error for now, as it can error with "Wallet already exists." // ignore the error for now, as it can error with "Wallet already exists."
_ = cXMRTaker.callGenerateFromKeys(skAKPriv, vkABPriv, kpABPub.Address(common.Mainnet), _ = cXMRTaker.callGenerateFromKeys(skAKPriv, vkABPriv, kpABPub.Address(common.Mainnet), walletFP, "")
fmt.Sprintf("test-wallet-%d", r), "")
err = cXMRTaker.refresh() err = cXMRTaker.refresh()
require.NoError(t, err) require.NoError(t, err)
balance, err = cXMRTaker.GetBalance(0) balance, err = cXMRTaker.GetBalance(0)
require.NoError(t, err) require.NoError(t, err)
require.NotEqual(t, 0, balance.Balance) require.Greater(t, balance.Balance, float64(0))
// transfer from account A+B back to XMRMaker's address // transfer from account A+B back to XMRMaker's address
_, err = cXMRTaker.Transfer(mcrypto.Address(xmrmakerAddr.Address), 0, 1) _, err = cXMRTaker.Transfer(mcrypto.Address(xmrmakerAddr.Address), 0, 1)
@@ -105,8 +101,8 @@ func TestClient_Transfer(t *testing.T) {
} }
func TestClient_CloseWallet(t *testing.T) { func TestClient_CloseWallet(t *testing.T) {
c := NewClient(common.DefaultXMRMakerMoneroEndpoint) c := NewClient(tests.CreateWalletRPCService(t))
err := c.OpenWallet("test-wallet", "") err := c.CreateWallet("test-wallet", "")
require.NoError(t, err) require.NoError(t, err)
err = c.CloseWallet() err = c.CloseWallet()
@@ -117,14 +113,18 @@ func TestClient_CloseWallet(t *testing.T) {
} }
func TestClient_GetAccounts(t *testing.T) { func TestClient_GetAccounts(t *testing.T) {
c := NewClient(common.DefaultXMRMakerMoneroEndpoint) c := NewClient(tests.CreateWalletRPCService(t))
err := c.CreateWallet("test-wallet", "")
require.NoError(t, err)
resp, err := c.GetAccounts() resp, err := c.GetAccounts()
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 1, len(resp.SubaddressAccounts)) require.Equal(t, 1, len(resp.SubaddressAccounts))
} }
func TestClient_GetHeight(t *testing.T) { func TestClient_GetHeight(t *testing.T) {
c := NewClient(common.DefaultXMRMakerMoneroEndpoint) c := NewClient(tests.CreateWalletRPCService(t))
err := c.CreateWallet("test-wallet", "")
require.NoError(t, err)
resp, err := c.GetHeight() resp, err := c.GetHeight()
require.NoError(t, err) require.NoError(t, err)
require.NotEqual(t, 0, resp) require.NotEqual(t, 0, resp)

View File

@@ -8,6 +8,7 @@ import (
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
mcrypto "github.com/noot/atomic-swap/crypto/monero" mcrypto "github.com/noot/atomic-swap/crypto/monero"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -19,7 +20,7 @@ func TestCallGenerateFromKeys(t *testing.T) {
r, err := rand.Int(rand.Reader, big.NewInt(999)) r, err := rand.Int(rand.Reader, big.NewInt(999))
require.NoError(t, err) require.NoError(t, err)
c := NewClient(common.DefaultXMRMakerMoneroEndpoint) c := NewClient(tests.CreateWalletRPCService(t))
err = c.callGenerateFromKeys(kp.SpendKey(), kp.ViewKey(), kp.Address(common.Mainnet), err = c.callGenerateFromKeys(kp.SpendKey(), kp.ViewKey(), kp.Address(common.Mainnet),
fmt.Sprintf("test-wallet-%d", r), "") fmt.Sprintf("test-wallet-%d", r), "")
require.NoError(t, err) require.NoError(t, err)

View File

@@ -53,7 +53,7 @@ func WaitForBlocks(client Client, count int) (uint, error) {
// CreateMoneroWallet creates a monero wallet from a private keypair. // CreateMoneroWallet creates a monero wallet from a private keypair.
func CreateMoneroWallet(name string, env common.Environment, client Client, func CreateMoneroWallet(name string, env common.Environment, client Client,
kpAB *mcrypto.PrivateKeyPair) (mcrypto.Address, error) { kpAB *mcrypto.PrivateKeyPair) (mcrypto.Address, error) {
t := time.Now().Format("2006-Jan-2-15:04:05") t := time.Now().Format("2006-01-02-15:04:05.999999999")
walletName := fmt.Sprintf("%s-%s", name, t) walletName := fmt.Sprintf("%s-%s", name, t)
if err := client.GenerateFromKeys(kpAB, walletName, "", env); err != nil { if err := client.GenerateFromKeys(kpAB, walletName, "", env); err != nil {
return "", err return "", err

View File

@@ -1,34 +1,41 @@
package monero package monero
import ( import (
"sync"
"testing" "testing"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
mcrypto "github.com/noot/atomic-swap/crypto/monero" mcrypto "github.com/noot/atomic-swap/crypto/monero"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestWaitForBlocks(t *testing.T) { func TestWaitForBlocks(t *testing.T) {
c := NewClient(common.DefaultXMRMakerMoneroEndpoint) c := NewClient(tests.CreateWalletRPCService(t))
require.NoError(t, c.CreateWallet("wallet", ""))
daemon := NewClient(common.DefaultMoneroDaemonEndpoint) daemon := NewClient(common.DefaultMoneroDaemonEndpoint)
addr, err := c.callGetAddress(0) addr, err := c.callGetAddress(0)
require.NoError(t, err) require.NoError(t, err)
var wg sync.WaitGroup
wg.Add(1)
go func() { go func() {
_ = daemon.callGenerateBlocks(addr.Address, 181) _ = daemon.callGenerateBlocks(addr.Address, 181)
wg.Done()
}() }()
_, err = WaitForBlocks(c, 1) _, err = WaitForBlocks(c, 1)
require.NoError(t, err) require.NoError(t, err)
wg.Wait()
} }
func TestCreateMoneroWallet(t *testing.T) { func TestCreateMoneroWallet(t *testing.T) {
kp, err := mcrypto.GenerateKeys() kp, err := mcrypto.GenerateKeys()
require.NoError(t, err) require.NoError(t, err)
c := NewClient(common.DefaultXMRMakerMoneroEndpoint) c := NewClient(tests.CreateWalletRPCService(t))
addr, err := CreateMoneroWallet("create-wallet-test", common.Development, c, kp) addr, err := CreateMoneroWallet("create-wallet-test", common.Development, c, kp)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, kp.Address(common.Development), addr) require.Equal(t, kp.Address(common.Development), addr)

View File

@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"path"
"testing" "testing"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
@@ -63,7 +64,7 @@ func newHost(t *testing.T, port uint16) *host {
Environment: common.Development, Environment: common.Development,
ChainID: common.GanacheChainID, ChainID: common.GanacheChainID,
Port: port, Port: port,
KeyFile: fmt.Sprintf("/tmp/node-%d.key", port), KeyFile: path.Join(t.TempDir(), fmt.Sprintf("node-%d.key", port)),
Bootnodes: []string{}, Bootnodes: []string{},
Handler: &mockHandler{}, Handler: &mockHandler{},
} }

View File

@@ -134,7 +134,7 @@ func (m *QueryResponse) Type() Type {
return QueryResponseType return QueryResponseType
} }
// The below messages are sawp protocol messages, exchanged after the swap has been agreed // The below messages are swap protocol messages, exchanged after the swap has been agreed
// upon by both sides. // upon by both sides.
// SendKeysMessage is sent by both parties to each other to initiate the protocol // SendKeysMessage is sent by both parties to each other to initiate the protocol

View File

@@ -1,17 +1,17 @@
package net package net
import ( import (
"os"
"testing" "testing"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestGenerateAndSaveKey(t *testing.T) { func TestGenerateAndSaveKey(t *testing.T) {
_, err := generateKey(1234, os.TempDir()) tempDir := t.TempDir()
_, err := generateKey(1234, tempDir)
require.NoError(t, err) require.NoError(t, err)
_, err = generateKey(1234, os.TempDir()) _, err = generateKey(1234, tempDir)
require.NoError(t, err) require.NoError(t, err)
} }

View File

@@ -2,10 +2,12 @@ package backend
import ( import (
"context" "context"
"crypto/ecdsa"
"math/big" "math/big"
"testing" "testing"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/tests"
ethcommon "github.com/ethereum/go-ethereum/common" ethcommon "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
@@ -14,30 +16,32 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
const defaultXMRTakerAddress = "0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1"
func TestWaitForReceipt(t *testing.T) { func TestWaitForReceipt(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
defer ec.Close()
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRTaker) privKey, err := ethcrypto.HexToECDSA(tests.GetTakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
nonce, err := ec.PendingNonceAt(ctx, ethcommon.HexToAddress(defaultXMRTakerAddress)) publicKey := privKey.Public().(*ecdsa.PublicKey)
nonce, err := ec.PendingNonceAt(ctx, ethcrypto.PubkeyToAddress(*publicKey))
require.NoError(t, err) require.NoError(t, err)
to := ethcommon.Address{} to := ethcommon.Address{}
txInner := &ethtypes.LegacyTx{ txInner := &ethtypes.LegacyTx{
Nonce: nonce, Nonce: nonce,
To: &to, To: &to,
Value: big.NewInt(99), Value: big.NewInt(99),
Gas: 21000, Gas: 21000,
GasPrice: big.NewInt(2000000000),
} }
tx, err := ethtypes.SignNewTx(pk, tx, err := ethtypes.SignNewTx(privKey,
ethtypes.LatestSignerForChainID(big.NewInt(common.GanacheChainID)), ethtypes.LatestSignerForChainID(big.NewInt(common.GanacheChainID)),
txInner, txInner,
) )

View File

@@ -2,6 +2,7 @@ package protocol
import ( import (
"fmt" "fmt"
"path"
"time" "time"
"github.com/noot/atomic-swap/net/message" "github.com/noot/atomic-swap/net/message"
@@ -9,17 +10,15 @@ import (
) )
// GetSwapInfoFilepath returns an info file path with the current timestamp. // GetSwapInfoFilepath returns an info file path with the current timestamp.
func GetSwapInfoFilepath(basepath string) string { func GetSwapInfoFilepath(basePath string) string {
t := time.Now().Format("2006-Jan-2-15:04:05") t := time.Now().Format("2006-01-02-15:04:05.999999999")
path := fmt.Sprintf("%s/info-%s.txt", basepath, t) return path.Join(basePath, t)
return path
} }
// GetSwapRecoveryFilepath returns an info file path with the current timestamp. // GetSwapRecoveryFilepath returns an info file path with the current timestamp.
func GetSwapRecoveryFilepath(basepath string) string { func GetSwapRecoveryFilepath(basePath string) string {
t := time.Now().Format("2006-Jan-2-15:04:05") t := time.Now().Format("2006-01-02-15:04:05.999999999")
path := fmt.Sprintf("%s/recovery-%s.txt", basepath, t) return path.Join(basePath, fmt.Sprintf("recovery-%s.txt", t))
return path
} }
// ConvertContractSwapToMsg converts a swapfactory.SwapFactorySwap to a *message.ContractSwap // ConvertContractSwapToMsg converts a swapfactory.SwapFactorySwap to a *message.ContractSwap

View File

@@ -1,7 +1,7 @@
package protocol package protocol
import ( import (
"os" "path"
"testing" "testing"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
@@ -14,12 +14,12 @@ func TestWriteKeysToFile(t *testing.T) {
kp, err := mcrypto.GenerateKeys() kp, err := mcrypto.GenerateKeys()
require.NoError(t, err) require.NoError(t, err)
err = WriteKeysToFile(os.TempDir()+"/test.keys", kp, common.Development) err = WriteKeysToFile(path.Join(t.TempDir(), "test.keys"), kp, common.Development)
require.NoError(t, err) require.NoError(t, err)
} }
func TestWriteContractAddrssToFile(t *testing.T) { func TestWriteContractAddrssToFile(t *testing.T) {
addr := "0xabcd" addr := "0xabcd"
err := WriteContractAddressToFile(os.TempDir()+"/test.keys", addr) err := WriteContractAddressToFile(path.Join(t.TempDir(), "test.keys"), addr)
require.NoError(t, err) require.NoError(t, err)
} }

View File

@@ -149,7 +149,7 @@ func (s *swapState) handleNotifyETHLocked(msg *message.NotifyETHLocked) (net.Mes
s.contractSwapID = msg.ContractSwapID s.contractSwapID = msg.ContractSwapID
s.contractSwap = convertContractSwap(msg.ContractSwap) s.contractSwap = convertContractSwap(msg.ContractSwap)
if err := pcommon.WriteContractSwapToFile(s.infofile, s.contractSwapID, s.contractSwap); err != nil { if err := pcommon.WriteContractSwapToFile(s.infoFile, s.contractSwapID, s.contractSwap); err != nil {
return nil, err return nil, err
} }
@@ -162,7 +162,7 @@ func (s *swapState) handleNotifyETHLocked(msg *message.NotifyETHLocked) (net.Mes
return nil, fmt.Errorf("failed to instantiate contract instance: %w", err) return nil, fmt.Errorf("failed to instantiate contract instance: %w", err)
} }
if err := pcommon.WriteContractAddressToFile(s.infofile, msg.Address); err != nil { if err := pcommon.WriteContractAddressToFile(s.infoFile, msg.Address); err != nil {
return nil, fmt.Errorf("failed to write contract address to file: %w", err) return nil, fmt.Errorf("failed to write contract address to file: %w", err)
} }

View File

@@ -19,7 +19,7 @@ type recoveryState struct {
// NewRecoveryState returns a new *xmrmaker.recoveryState, // NewRecoveryState returns a new *xmrmaker.recoveryState,
// which has methods to either claim ether or reclaim monero from an initiated swap. // which has methods to either claim ether or reclaim monero from an initiated swap.
func NewRecoveryState(b backend.Backend, basepath string, secret *mcrypto.PrivateSpendKey, func NewRecoveryState(b backend.Backend, basePath string, secret *mcrypto.PrivateSpendKey,
contractAddr ethcommon.Address, contractAddr ethcommon.Address,
contractSwapID [32]byte, contractSwap swapfactory.SwapFactorySwap) (*recoveryState, error) { //nolint:revive contractSwapID [32]byte, contractSwap swapfactory.SwapFactorySwap) (*recoveryState, error) { //nolint:revive
kp, err := secret.AsPrivateKeyPair() kp, err := secret.AsPrivateKeyPair()
@@ -42,7 +42,7 @@ func NewRecoveryState(b backend.Backend, basepath string, secret *mcrypto.Privat
dleqProof: dleq.NewProofWithSecret(sc), dleqProof: dleq.NewProofWithSecret(sc),
contractSwapID: contractSwapID, contractSwapID: contractSwapID,
contractSwap: contractSwap, contractSwap: contractSwap,
infofile: pcommon.GetSwapRecoveryFilepath(basepath), infoFile: pcommon.GetSwapRecoveryFilepath(basePath),
} }
if err := s.setContract(contractAddr); err != nil { if err := s.setContract(contractAddr); err != nil {

View File

@@ -2,6 +2,7 @@ package xmrmaker
import ( import (
"math/big" "math/big"
"path"
"testing" "testing"
"time" "time"
@@ -23,7 +24,8 @@ func newTestRecoveryState(t *testing.T) *recoveryState {
require.NoError(t, err) require.NoError(t, err)
newSwap(t, s, [32]byte{}, sr, big.NewInt(1), duration) newSwap(t, s, [32]byte{}, sr, big.NewInt(1), duration)
rs, err := NewRecoveryState(inst.backend, "/tmp/test-infofile", s.privkeys.SpendKey(), s.ContractAddr(), basePath := path.Join(t.TempDir(), "test-infofile")
rs, err := NewRecoveryState(inst.backend, basePath, s.privkeys.SpendKey(), s.ContractAddr(),
s.contractSwapID, s.contractSwap) s.contractSwapID, s.contractSwap)
require.NoError(t, err) require.NoError(t, err)

View File

@@ -43,7 +43,7 @@ type swapState struct {
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
sync.Mutex sync.Mutex
infofile string infoFile string
info *pswap.Info info *pswap.Info
offer *types.Offer offer *types.Offer
@@ -77,7 +77,7 @@ type swapState struct {
moneroReclaimAddress mcrypto.Address moneroReclaimAddress mcrypto.Address
} }
func newSwapState(b backend.Backend, offer *types.Offer, om *offerManager, statusCh chan types.Status, infofile string, func newSwapState(b backend.Backend, offer *types.Offer, om *offerManager, statusCh chan types.Status, infoFile string,
providesAmount common.MoneroAmount, desiredAmount common.EtherAmount) (*swapState, error) { providesAmount common.MoneroAmount, desiredAmount common.EtherAmount) (*swapState, error) {
exchangeRate := types.ExchangeRate(providesAmount.AsMonero() / desiredAmount.AsEther()) exchangeRate := types.ExchangeRate(providesAmount.AsMonero() / desiredAmount.AsEther())
stage := types.ExpectingKeys stage := types.ExpectingKeys
@@ -98,7 +98,7 @@ func newSwapState(b backend.Backend, offer *types.Offer, om *offerManager, statu
Backend: b, Backend: b,
offer: offer, offer: offer,
offerManager: om, offerManager: om,
infofile: infofile, infoFile: infoFile,
nextExpectedMessage: &net.SendKeysMessage{}, nextExpectedMessage: &net.SendKeysMessage{},
readyCh: make(chan struct{}), readyCh: make(chan struct{}),
info: info, info: info,
@@ -125,9 +125,9 @@ func (s *swapState) SendKeysMessage() (*net.SendKeysMessage, error) {
}, nil }, nil
} }
// InfoFile returns the swap's infofile path // InfoFile returns the swap's infoFile path
func (s *swapState) InfoFile() string { func (s *swapState) InfoFile() string {
return s.infofile return s.infoFile
} }
// ReceivedAmount returns the amount received, or expected to be received, at the end of the swap // ReceivedAmount returns the amount received, or expected to be received, at the end of the swap
@@ -261,7 +261,7 @@ func (s *swapState) reclaimMonero(skA *mcrypto.PrivateSpendKey) (mcrypto.Address
kpAB := mcrypto.NewPrivateKeyPair(skAB, vkAB) kpAB := mcrypto.NewPrivateKeyPair(skAB, vkAB)
// write keys to file in case something goes wrong // write keys to file in case something goes wrong
if err = pcommon.WriteSharedSwapKeyPairToFile(s.infofile, kpAB, s.Env()); err != nil { if err = pcommon.WriteSharedSwapKeyPairToFile(s.infoFile, kpAB, s.Env()); err != nil {
return "", err return "", err
} }
@@ -361,7 +361,7 @@ func (s *swapState) generateAndSetKeys() error {
s.privkeys = keysAndProof.PrivateKeyPair s.privkeys = keysAndProof.PrivateKeyPair
s.pubkeys = keysAndProof.PublicKeyPair s.pubkeys = keysAndProof.PublicKeyPair
return pcommon.WriteKeysToFile(s.infofile, s.privkeys, s.Env()) return pcommon.WriteKeysToFile(s.infoFile, s.privkeys, s.Env())
} }
func generateKeys() (*pcommon.KeysAndProof, error) { func generateKeys() (*pcommon.KeysAndProof, error) {

View File

@@ -4,18 +4,20 @@ import (
"context" "context"
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"os" "path"
"testing" "testing"
"time" "time"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/common/types" "github.com/noot/atomic-swap/common/types"
"github.com/noot/atomic-swap/monero"
"github.com/noot/atomic-swap/net" "github.com/noot/atomic-swap/net"
"github.com/noot/atomic-swap/net/message" "github.com/noot/atomic-swap/net/message"
pcommon "github.com/noot/atomic-swap/protocol" pcommon "github.com/noot/atomic-swap/protocol"
"github.com/noot/atomic-swap/protocol/backend" "github.com/noot/atomic-swap/protocol/backend"
pswap "github.com/noot/atomic-swap/protocol/swap" pswap "github.com/noot/atomic-swap/protocol/swap"
"github.com/noot/atomic-swap/swapfactory" "github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
ethcommon "github.com/ethereum/go-ethereum/common" ethcommon "github.com/ethereum/go-ethereum/common"
@@ -25,8 +27,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var infofile = os.TempDir() + "/test.keys"
var ( var (
_ = logging.SetLogLevel("xmrmaker", "debug") _ = logging.SetLogLevel("xmrmaker", "debug")
testWallet = "test-wallet" testWallet = "test-wallet"
@@ -47,11 +47,14 @@ var (
) )
func newTestXMRMaker(t *testing.T) *Instance { func newTestXMRMaker(t *testing.T) *Instance {
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRMaker) pk, err := ethcrypto.HexToECDSA(tests.GetMakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
ec.Close()
})
txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.GanacheChainID)) txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.GanacheChainID))
require.NoError(t, err) require.NoError(t, err)
@@ -61,12 +64,12 @@ func newTestXMRMaker(t *testing.T) *Instance {
bcfg := &backend.Config{ bcfg := &backend.Config{
Ctx: context.Background(), Ctx: context.Background(),
MoneroWalletEndpoint: common.DefaultXMRMakerMoneroEndpoint, MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint, MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
EthereumClient: ec, EthereumClient: ec,
EthereumPrivateKey: pk, EthereumPrivateKey: pk,
Environment: common.Development, Environment: common.Development,
ChainID: big.NewInt(common.MainnetConfig.EthereumChainID), ChainID: big.NewInt(common.DevelopmentConfig.EthereumChainID),
SwapContract: contract, SwapContract: contract,
SwapContractAddress: addr, SwapContractAddress: addr,
SwapManager: pswap.NewManager(), SwapManager: pswap.NewManager(),
@@ -78,11 +81,15 @@ func newTestXMRMaker(t *testing.T) *Instance {
cfg := &Config{ cfg := &Config{
Backend: b, Backend: b,
Basepath: "/tmp/xmrmaker", Basepath: path.Join(t.TempDir(), "xmrmaker"),
WalletFile: testWallet, WalletFile: testWallet,
WalletPassword: "", WalletPassword: "",
} }
// NewInstance(..) below expects a pre-existing wallet, so create it
err = monero.NewClient(bcfg.MoneroWalletEndpoint).CreateWallet(cfg.WalletFile, "")
require.NoError(t, err)
xmrmaker, err := NewInstance(cfg) xmrmaker, err := NewInstance(cfg)
require.NoError(t, err) require.NoError(t, err)
@@ -97,7 +104,8 @@ func newTestXMRMaker(t *testing.T) *Instance {
func newTestInstance(t *testing.T) (*Instance, *swapState) { func newTestInstance(t *testing.T) (*Instance, *swapState) {
xmrmaker := newTestXMRMaker(t) xmrmaker := newTestXMRMaker(t)
swapState, err := newSwapState(xmrmaker.backend, &types.Offer{}, xmrmaker.offerManager, nil, infofile, infoFile := path.Join(t.TempDir(), "test.keys")
swapState, err := newSwapState(xmrmaker.backend, &types.Offer{}, xmrmaker.offerManager, nil, infoFile,
common.MoneroAmount(33), desiredAmount) common.MoneroAmount(33), desiredAmount)
require.NoError(t, err) require.NoError(t, err)
swapState.SetContract(xmrmaker.backend.Contract()) swapState.SetContract(xmrmaker.backend.Contract())

View File

@@ -7,6 +7,7 @@ import (
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/swapfactory" "github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
ethcommon "github.com/ethereum/go-ethereum/common" ethcommon "github.com/ethereum/go-ethereum/common"
@@ -23,8 +24,9 @@ func TestCheckContractCode(t *testing.T) {
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
defer ec.Close()
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRMaker) pk, err := ethcrypto.HexToECDSA(tests.GetMakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.GanacheChainID)) txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.GanacheChainID))

View File

@@ -3,14 +3,14 @@ package xmrtaker
import ( import (
"testing" "testing"
"github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/monero" "github.com/noot/atomic-swap/monero"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestGetAddress(t *testing.T) { func TestGetAddress(t *testing.T) {
c := monero.NewClient(common.DefaultXMRTakerMoneroEndpoint) c := monero.NewClient(tests.CreateWalletRPCService(t))
addr, err := getAddress(c, "", "") addr, err := getAddress(c, "", "")
require.NoError(t, err) require.NoError(t, err)

View File

@@ -216,7 +216,7 @@ func (s *swapState) handleNotifyXMRLock(msg *message.NotifyXMRLock) (net.Message
s.LockClient() s.LockClient()
defer s.UnlockClient() defer s.UnlockClient()
t := time.Now().Format("2006-Jan-2-15:04:05") t := time.Now().Format("2006-01-02-15:04:05.999999999")
walletName := fmt.Sprintf("xmrtaker-viewonly-wallet-%s", t) walletName := fmt.Sprintf("xmrtaker-viewonly-wallet-%s", t)
if err := s.GenerateViewOnlyWalletFromKeys(vk, kp.Address(s.Env()), walletName, ""); err != nil { if err := s.GenerateViewOnlyWalletFromKeys(vk, kp.Address(s.Env()), walletName, ""); err != nil {
return nil, fmt.Errorf("failed to generate view-only wallet to verify locked XMR: %w", err) return nil, fmt.Errorf("failed to generate view-only wallet to verify locked XMR: %w", err)

View File

@@ -1,10 +1,13 @@
package xmrtaker package xmrtaker
import ( import (
"path"
"testing" "testing"
"github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/common/types" "github.com/noot/atomic-swap/common/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -12,7 +15,7 @@ func newTestXMRTaker(t *testing.T) *Instance {
b := newBackend(t) b := newBackend(t)
cfg := &Config{ cfg := &Config{
Backend: b, Backend: b,
Basepath: "/tmp/xmrtaker", Basepath: path.Join(t.TempDir(), "xmrtaker"),
} }
xmrtaker, err := NewInstance(cfg) xmrtaker, err := NewInstance(cfg)
@@ -21,6 +24,10 @@ func newTestXMRTaker(t *testing.T) *Instance {
} }
func TestXMRTaker_InitiateProtocol(t *testing.T) { func TestXMRTaker_InitiateProtocol(t *testing.T) {
ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err)
defer ec.Close()
a := newTestXMRTaker(t) a := newTestXMRTaker(t)
offer := &types.Offer{ offer := &types.Offer{
ExchangeRate: 1, ExchangeRate: 1,

View File

@@ -25,7 +25,7 @@ type recoveryState struct {
// NewRecoveryState returns a new *xmrmaker.recoveryState, // NewRecoveryState returns a new *xmrmaker.recoveryState,
// which has methods to either claim ether or reclaim monero from an initiated swap. // which has methods to either claim ether or reclaim monero from an initiated swap.
func NewRecoveryState(b backend.Backend, basepath string, secret *mcrypto.PrivateSpendKey, func NewRecoveryState(b backend.Backend, basePath string, secret *mcrypto.PrivateSpendKey,
contractSwapID [32]byte, contractSwap swapfactory.SwapFactorySwap) (*recoveryState, error) { //nolint:revive contractSwapID [32]byte, contractSwap swapfactory.SwapFactorySwap) (*recoveryState, error) { //nolint:revive
kp, err := secret.AsPrivateKeyPair() kp, err := secret.AsPrivateKeyPair()
if err != nil { if err != nil {
@@ -47,7 +47,7 @@ func NewRecoveryState(b backend.Backend, basepath string, secret *mcrypto.Privat
dleqProof: dleq.NewProofWithSecret(sc), dleqProof: dleq.NewProofWithSecret(sc),
contractSwapID: contractSwapID, contractSwapID: contractSwapID,
contractSwap: contractSwap, contractSwap: contractSwap,
infofile: pcommon.GetSwapRecoveryFilepath(basepath), infoFile: pcommon.GetSwapRecoveryFilepath(basePath),
claimedCh: make(chan struct{}), claimedCh: make(chan struct{}),
} }
@@ -68,8 +68,7 @@ type RecoveryResult struct {
MoneroAddress mcrypto.Address MoneroAddress mcrypto.Address
} }
// ClaimOrRecover either claims ether or recovers monero by creating a wallet. // ClaimOrRefund either claims the monero or recovers the ether returning a *RecoveryResult.
// It returns a *RecoveryResult.
func (rs *recoveryState) ClaimOrRefund() (*RecoveryResult, error) { func (rs *recoveryState) ClaimOrRefund() (*RecoveryResult, error) {
// check if XMRMaker claimed // check if XMRMaker claimed
skA, err := rs.ss.filterForClaim() skA, err := rs.ss.filterForClaim()

View File

@@ -1,6 +1,7 @@
package xmrtaker package xmrtaker
import ( import (
"path"
"testing" "testing"
"time" "time"
@@ -27,7 +28,8 @@ func newTestRecoveryState(t *testing.T) *recoveryState {
_, err = s.lockETH(common.NewEtherAmount(1)) _, err = s.lockETH(common.NewEtherAmount(1))
require.NoError(t, err) require.NoError(t, err)
rs, err := NewRecoveryState(s, "/tmp/test-infofile", s.privkeys.SpendKey(), s.contractSwapID, s.contractSwap) basePath := path.Join(t.TempDir(), "test-infoFile")
rs, err := NewRecoveryState(s, basePath, s.privkeys.SpendKey(), s.contractSwapID, s.contractSwap)
require.NoError(t, err) require.NoError(t, err)
return rs return rs
} }

View File

@@ -36,7 +36,7 @@ type swapState struct {
ctx context.Context ctx context.Context
cancel context.CancelFunc cancel context.CancelFunc
sync.Mutex sync.Mutex
infofile string infoFile string
transferBack bool transferBack bool
info *pswap.Info info *pswap.Info
@@ -99,7 +99,7 @@ func newSwapState(b backend.Backend, offerID types.Hash, infofile string, transf
ctx: ctx, ctx: ctx,
cancel: cancel, cancel: cancel,
Backend: b, Backend: b,
infofile: infofile, infoFile: infofile,
transferBack: transferBack, transferBack: transferBack,
nextExpectedMessage: &net.SendKeysMessage{}, nextExpectedMessage: &net.SendKeysMessage{},
xmrLockedCh: make(chan struct{}), xmrLockedCh: make(chan struct{}),
@@ -109,7 +109,7 @@ func newSwapState(b backend.Backend, offerID types.Hash, infofile string, transf
statusCh: statusCh, statusCh: statusCh,
} }
if err := pcommon.WriteContractAddressToFile(s.infofile, b.ContractAddr().String()); err != nil { if err := pcommon.WriteContractAddressToFile(s.infoFile, b.ContractAddr().String()); err != nil {
return nil, fmt.Errorf("failed to write contract address to file: %w", err) return nil, fmt.Errorf("failed to write contract address to file: %w", err)
} }
@@ -149,9 +149,9 @@ func (s *swapState) SendKeysMessage() (*net.SendKeysMessage, error) {
}, nil }, nil
} }
// InfoFile returns the swap's infofile path // InfoFile returns the swap's infoFile path
func (s *swapState) InfoFile() string { func (s *swapState) InfoFile() string {
return s.infofile return s.infoFile
} }
// ReceivedAmount returns the amount received, or expected to be received, at the end of the swap // ReceivedAmount returns the amount received, or expected to be received, at the end of the swap
@@ -344,7 +344,7 @@ func (s *swapState) generateAndSetKeys() error {
s.privkeys = keysAndProof.PrivateKeyPair s.privkeys = keysAndProof.PrivateKeyPair
s.pubkeys = keysAndProof.PublicKeyPair s.pubkeys = keysAndProof.PublicKeyPair
return pcommon.WriteKeysToFile(s.infofile, s.privkeys, s.Env()) return pcommon.WriteKeysToFile(s.infoFile, s.privkeys, s.Env())
} }
// generateKeys generates XMRTaker's monero spend and view keys (S_b, V_b), a secp256k1 public key, // generateKeys generates XMRTaker's monero spend and view keys (S_b, V_b), a secp256k1 public key,
@@ -419,7 +419,7 @@ func (s *swapState) lockETH(amount common.EtherAmount) (ethcommon.Hash, error) {
Nonce: nonce, Nonce: nonce,
} }
if err := pcommon.WriteContractSwapToFile(s.infofile, s.contractSwapID, s.contractSwap); err != nil { if err := pcommon.WriteContractSwapToFile(s.infoFile, s.contractSwapID, s.contractSwap); err != nil {
return ethcommon.Hash{}, err return ethcommon.Hash{}, err
} }
@@ -472,7 +472,7 @@ func (s *swapState) claimMonero(skB *mcrypto.PrivateSpendKey) (mcrypto.Address,
kpAB := mcrypto.NewPrivateKeyPair(skAB, vkAB) kpAB := mcrypto.NewPrivateKeyPair(skAB, vkAB)
// write keys to file in case something goes wrong // write keys to file in case something goes wrong
if err := pcommon.WriteSharedSwapKeyPairToFile(s.infofile, kpAB, s.Env()); err != nil { if err := pcommon.WriteSharedSwapKeyPairToFile(s.infoFile, kpAB, s.Env()); err != nil {
return "", err return "", err
} }

View File

@@ -21,6 +21,7 @@ import (
"github.com/noot/atomic-swap/protocol/backend" "github.com/noot/atomic-swap/protocol/backend"
pswap "github.com/noot/atomic-swap/protocol/swap" pswap "github.com/noot/atomic-swap/protocol/swap"
"github.com/noot/atomic-swap/swapfactory" "github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
logging "github.com/ipfs/go-log" logging "github.com/ipfs/go-log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@@ -40,25 +41,28 @@ func (n *mockNet) SendSwapMessage(msg net.Message, _ types.Hash) error {
} }
func newBackend(t *testing.T) backend.Backend { func newBackend(t *testing.T) backend.Backend {
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRTaker) pk, err := ethcrypto.HexToECDSA(tests.GetTakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
ec.Close()
})
txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.MainnetConfig.EthereumChainID)) txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.DevelopmentConfig.EthereumChainID))
require.NoError(t, err) require.NoError(t, err)
addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec) addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec)
require.NoError(t, err) require.NoError(t, err)
bcfg := &backend.Config{ bcfg := &backend.Config{
Ctx: context.Background(), Ctx: context.Background(),
MoneroWalletEndpoint: common.DefaultXMRTakerMoneroEndpoint, MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint, MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
EthereumClient: ec, EthereumClient: ec,
EthereumPrivateKey: pk, EthereumPrivateKey: pk,
Environment: common.Development, Environment: common.Development,
ChainID: big.NewInt(common.MainnetConfig.EthereumChainID), ChainID: big.NewInt(common.DevelopmentConfig.EthereumChainID),
SwapManager: pswap.NewManager(), SwapManager: pswap.NewManager(),
SwapContract: contract, SwapContract: contract,
SwapContractAddress: addr, SwapContractAddress: addr,
@@ -71,25 +75,26 @@ func newBackend(t *testing.T) backend.Backend {
} }
func newXMRMakerBackend(t *testing.T) backend.Backend { func newXMRMakerBackend(t *testing.T) backend.Backend {
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRMaker) pk, err := ethcrypto.HexToECDSA(tests.GetMakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
defer ec.Close()
txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.MainnetConfig.EthereumChainID)) txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.DevelopmentConfig.EthereumChainID))
require.NoError(t, err) require.NoError(t, err)
addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec) addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec)
require.NoError(t, err) require.NoError(t, err)
bcfg := &backend.Config{ bcfg := &backend.Config{
Ctx: context.Background(), Ctx: context.Background(),
MoneroWalletEndpoint: common.DefaultXMRMakerMoneroEndpoint, MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint, MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
EthereumClient: ec, EthereumClient: ec,
EthereumPrivateKey: pk, EthereumPrivateKey: pk,
Environment: common.Development, Environment: common.Development,
ChainID: big.NewInt(common.MainnetConfig.EthereumChainID), ChainID: big.NewInt(common.DevelopmentConfig.EthereumChainID),
SwapManager: pswap.NewManager(), SwapManager: pswap.NewManager(),
SwapContract: contract, SwapContract: contract,
SwapContractAddress: addr, SwapContractAddress: addr,
@@ -278,7 +283,7 @@ func TestSwapState_NotifyClaimed(t *testing.T) {
// close swap-deposit-wallet // close swap-deposit-wallet
maker := newXMRMakerBackend(t) maker := newXMRMakerBackend(t)
err := maker.OpenWallet("test-wallet", "") err := maker.CreateWallet("test-wallet", "")
require.NoError(t, err) require.NoError(t, err)
// invalid SendKeysMessage should result in an error // invalid SendKeysMessage should result in an error
@@ -308,7 +313,10 @@ func TestSwapState_NotifyClaimed(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// mine some blocks to get xmr first // mine some blocks to get xmr first
_ = maker.GenerateBlocks(xmrmakerAddr.Address, 60) err = maker.GenerateBlocks(xmrmakerAddr.Address, 60)
require.NoError(t, err)
err = maker.Refresh()
require.NoError(t, err)
amt := common.MoneroAmount(1000000000) amt := common.MoneroAmount(1000000000)
kp := mcrypto.SumSpendAndViewKeys(s.pubkeys, s.pubkeys) kp := mcrypto.SumSpendAndViewKeys(s.pubkeys, s.pubkeys)
xmrAddr := kp.Address(common.Mainnet) xmrAddr := kp.Address(common.Mainnet)
@@ -331,7 +339,7 @@ func TestSwapState_NotifyClaimed(t *testing.T) {
require.NotNil(t, resp) require.NotNil(t, resp)
require.Equal(t, message.NotifyReadyType, resp.Type()) require.Equal(t, message.NotifyReadyType, resp.Type())
_ = maker.GenerateBlocks(xmrmakerAddr.Address, 1) err = maker.GenerateBlocks(xmrmakerAddr.Address, 1)
require.NoError(t, err) require.NoError(t, err)
// simulate xmrmaker calling claim // simulate xmrmaker calling claim

View File

@@ -89,7 +89,7 @@ func (r *recoverer) WalletFromSharedSecret(pk *mcrypto.PrivateKeyInfo) (mcrypto.
} }
// RecoverFromXMRMakerSecretAndContract recovers funds by either claiming ether or reclaiming locked monero. // RecoverFromXMRMakerSecretAndContract recovers funds by either claiming ether or reclaiming locked monero.
func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, basepath string, func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, basePath string,
xmrmakerSecret, contractAddr string, swapID [32]byte, xmrmakerSecret, contractAddr string, swapID [32]byte,
swap swapfactory.SwapFactorySwap) (*xmrmaker.RecoveryResult, error) { swap swapfactory.SwapFactorySwap) (*xmrmaker.RecoveryResult, error) {
bs, err := hex.DecodeString(xmrmakerSecret) bs, err := hex.DecodeString(xmrmakerSecret)
@@ -103,7 +103,7 @@ func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, base
} }
addr := ethcommon.HexToAddress(contractAddr) addr := ethcommon.HexToAddress(contractAddr)
rs, err := xmrmaker.NewRecoveryState(b, basepath, bk, addr, swapID, swap) rs, err := xmrmaker.NewRecoveryState(b, basePath, bk, addr, swapID, swap)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -112,7 +112,7 @@ func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, base
} }
// RecoverFromXMRTakerSecretAndContract recovers funds by either claiming locked monero or refunding ether. // RecoverFromXMRTakerSecretAndContract recovers funds by either claiming locked monero or refunding ether.
func (r *recoverer) RecoverFromXMRTakerSecretAndContract(b backend.Backend, basepath string, func (r *recoverer) RecoverFromXMRTakerSecretAndContract(b backend.Backend, basePath string,
xmrtakerSecret string, swapID [32]byte, swap swapfactory.SwapFactorySwap) (*xmrtaker.RecoveryResult, error) { xmrtakerSecret string, swapID [32]byte, swap swapfactory.SwapFactorySwap) (*xmrtaker.RecoveryResult, error) {
as, err := hex.DecodeString(xmrtakerSecret) as, err := hex.DecodeString(xmrtakerSecret)
if err != nil { if err != nil {
@@ -124,7 +124,7 @@ func (r *recoverer) RecoverFromXMRTakerSecretAndContract(b backend.Backend, base
return nil, err return nil, err
} }
rs, err := xmrtaker.NewRecoveryState(b, basepath, ak, swapID, swap) rs, err := xmrtaker.NewRecoveryState(b, basePath, ak, swapID, swap)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -3,6 +3,7 @@ package recovery
import ( import (
"context" "context"
"math/big" "math/big"
"path"
"testing" "testing"
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
@@ -10,6 +11,7 @@ import (
pcommon "github.com/noot/atomic-swap/protocol" pcommon "github.com/noot/atomic-swap/protocol"
"github.com/noot/atomic-swap/protocol/backend" "github.com/noot/atomic-swap/protocol/backend"
"github.com/noot/atomic-swap/swapfactory" "github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
ethcommon "github.com/ethereum/go-ethereum/common" ethcommon "github.com/ethereum/go-ethereum/common"
@@ -18,19 +20,28 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var defaulTimeout int64 = 5 // 5 seconds var defaultTimeout int64 = 5 // 5 seconds
func newRecoverer(t *testing.T) *recoverer { func newRecoverer(t *testing.T) *recoverer {
r, err := NewRecoverer(common.Development, common.DefaultXMRMakerMoneroEndpoint, common.DefaultEthEndpoint) r, err := NewRecoverer(common.Development, tests.CreateWalletRPCService(t), common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
return r return r
} }
func newSwap(t *testing.T, claimKey, refundKey [32]byte, func newSwap(
setReady bool) (ethcommon.Address, *swapfactory.SwapFactory, [32]byte, swapfactory.SwapFactorySwap) { t *testing.T,
tm := big.NewInt(defaulTimeout) claimKey [32]byte,
refundKey [32]byte,
setReady bool,
) (
ethcommon.Address,
*swapfactory.SwapFactory,
[32]byte,
swapfactory.SwapFactorySwap,
) {
tm := big.NewInt(defaultTimeout)
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRTaker) pk, err := ethcrypto.HexToECDSA(tests.GetTakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.GanacheChainID)) txOpts, err := bind.NewKeyedTransactorWithChainID(pk, big.NewInt(common.GanacheChainID))
@@ -38,11 +49,14 @@ func newSwap(t *testing.T, claimKey, refundKey [32]byte,
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
ec.Close()
})
addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec) addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec)
require.NoError(t, err) require.NoError(t, err)
pkXMRMaker, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRMaker) pkXMRMaker, err := ethcrypto.HexToECDSA(tests.GetMakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
nonce := big.NewInt(0) nonce := big.NewInt(0)
@@ -79,13 +93,20 @@ func newSwap(t *testing.T, claimKey, refundKey [32]byte,
return addr, contract, swapID, swap return addr, contract, swapID, swap
} }
func newBackend(t *testing.T, addr ethcommon.Address, contract *swapfactory.SwapFactory, func newBackend(
privkey string) backend.Backend { t *testing.T,
addr ethcommon.Address,
contract *swapfactory.SwapFactory,
privkey string,
) backend.Backend {
pk, err := ethcrypto.HexToECDSA(privkey) pk, err := ethcrypto.HexToECDSA(privkey)
require.NoError(t, err) require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint) ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
t.Cleanup(func() {
ec.Close()
})
cfg := &backend.Config{ cfg := &backend.Config{
Ctx: context.Background(), Ctx: context.Background(),
@@ -93,7 +114,7 @@ func newBackend(t *testing.T, addr ethcommon.Address, contract *swapfactory.Swap
EthereumPrivateKey: pk, EthereumPrivateKey: pk,
EthereumClient: ec, EthereumClient: ec,
ChainID: big.NewInt(common.GanacheChainID), ChainID: big.NewInt(common.GanacheChainID),
MoneroWalletEndpoint: common.DefaultXMRTakerMoneroEndpoint, MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint, MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
SwapContract: contract, SwapContract: contract,
SwapContractAddress: addr, SwapContractAddress: addr,
@@ -126,10 +147,11 @@ func TestRecoverer_RecoverFromXMRMakerSecretAndContract_Claim(t *testing.T) {
claimKey := keys.Secp256k1PublicKey.Keccak256() claimKey := keys.Secp256k1PublicKey.Keccak256()
addr, contract, swapID, swap := newSwap(t, claimKey, [32]byte{}, true) addr, contract, swapID, swap := newSwap(t, claimKey, [32]byte{}, true)
b := newBackend(t, addr, contract, common.DefaultPrivKeyXMRMaker) b := newBackend(t, addr, contract, tests.GetMakerTestKey(t))
r := newRecoverer(t) r := newRecoverer(t)
res, err := r.RecoverFromXMRMakerSecretAndContract(b, "/tmp/test-infofile", keys.PrivateKeyPair.SpendKey().Hex(), basePath := path.Join(t.TempDir(), "test-infofile")
res, err := r.RecoverFromXMRMakerSecretAndContract(b, basePath, keys.PrivateKeyPair.SpendKey().Hex(),
addr.String(), swapID, swap) addr.String(), swapID, swap)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Claimed) require.True(t, res.Claimed)
@@ -145,10 +167,11 @@ func TestRecoverer_RecoverFromXMRMakerSecretAndContract_Claim_afterTimeout(t *te
claimKey := keys.Secp256k1PublicKey.Keccak256() claimKey := keys.Secp256k1PublicKey.Keccak256()
addr, contract, swapID, swap := newSwap(t, claimKey, [32]byte{}, false) addr, contract, swapID, swap := newSwap(t, claimKey, [32]byte{}, false)
b := newBackend(t, addr, contract, common.DefaultPrivKeyXMRMaker) b := newBackend(t, addr, contract, tests.GetMakerTestKey(t))
r := newRecoverer(t) r := newRecoverer(t)
res, err := r.RecoverFromXMRMakerSecretAndContract(b, "/tmp/test-infofile", keys.PrivateKeyPair.SpendKey().Hex(), basePath := path.Join(t.TempDir(), "test-infofile")
res, err := r.RecoverFromXMRMakerSecretAndContract(b, basePath, keys.PrivateKeyPair.SpendKey().Hex(),
addr.String(), swapID, swap) addr.String(), swapID, swap)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Claimed) require.True(t, res.Claimed)
@@ -164,10 +187,11 @@ func TestRecoverer_RecoverFromXMRTakerSecretAndContract_Refund(t *testing.T) {
refundKey := keys.Secp256k1PublicKey.Keccak256() refundKey := keys.Secp256k1PublicKey.Keccak256()
addr, contract, swapID, swap := newSwap(t, [32]byte{}, refundKey, false) addr, contract, swapID, swap := newSwap(t, [32]byte{}, refundKey, false)
b := newBackend(t, addr, contract, common.DefaultPrivKeyXMRTaker) b := newBackend(t, addr, contract, tests.GetTakerTestKey(t))
r := newRecoverer(t) r := newRecoverer(t)
res, err := r.RecoverFromXMRTakerSecretAndContract(b, "/tmp/test-infofile", keys.PrivateKeyPair.SpendKey().Hex(), basePath := path.Join(t.TempDir(), "test-infofile")
res, err := r.RecoverFromXMRTakerSecretAndContract(b, basePath, keys.PrivateKeyPair.SpendKey().Hex(),
swapID, swap) swapID, swap)
require.NoError(t, err) require.NoError(t, err)
require.True(t, res.Refunded) require.True(t, res.Refunded)

7
scripts/install-lint.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
GOBIN="$(go env GOPATH)/bin"
if [[ ! -x "${GOBIN}/golangci-lint" ]]; then
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b "${GOBIN}" v1.46.2
fi

View File

@@ -1,9 +1,17 @@
#!/bin/bash #!/bin/bash
if [[ -d "./monero-x86_64-linux-gnu-v0.17.3.2" ]]; then arch=linux64
echo "monero-x86_64-linux-gnu-v0.17.3.2 already installed"
if [[ -d "monero-bin" ]]; then
echo "$(dirname $(realpath monero-bin)) already installed"
exit 0 exit 0
fi fi
curl -L https://downloads.getmonero.org/cli/linux64 > monero.tar.bz2 set -e
curl -L "https://downloads.getmonero.org/cli/${arch}" -o monero.tar.bz2
tar xjvf monero.tar.bz2 tar xjvf monero.tar.bz2
# Give the architecture and version specific release dir a fixed "monero-bin" symlink
versioned_dir="$(basename "$(tar tjf monero.tar.bz2 | head -1)")"
ln -sf "${versioned_dir}" monero-bin

View File

@@ -1,12 +0,0 @@
#!/bin/bash
if [[ -z "${GOPATH}" ]]; then
export GOPATH=~/go
fi
if ! command -v golangci-lint &> /dev/null
then
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.45.0
fi
export PATH=$PATH:$(go env GOPATH)/bin

View File

@@ -1,31 +1,34 @@
#!/bin/bash #!/bin/bash
# install monero and run daemon and wallet RPC servers for alice and bob # install monero and run daemon and wallet RPC servers for alice and bob
bash ./scripts/install-monero-linux.sh ./scripts/install-monero-linux.sh
echo "starting monerod..." echo "starting monerod..."
./monero-x86_64-linux-gnu-v0.17.3.2/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-port 18081 & ./monero-bin/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18081
sleep 5 sleep 5
echo "starting monero-wallet-rpc on port 18083..." echo "starting monero-wallet-rpc on port 18083..."
mkdir bob-test-keys mkdir -p bob-test-keys
./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log & ./monero-bin/monero-wallet-rpc --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log &
MONERO_WALLET_CLI_BOB_PID=$! MONERO_WALLET_CLI_BOB_PID=$!
sleep 5 sleep 5
curl http://localhost:18083/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"test-wallet","password":"","language":"English"}}' -H 'Content-Type: application/json' curl http://localhost:18083/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"test-wallet","password":"","language":"English"}}' -H 'Content-Type: application/json'
echo
echo "starting monero-wallet-rpc on port 18084..." echo "starting monero-wallet-rpc on port 18084..."
mkdir alice-test-keys mkdir -p alice-test-keys
./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log & ./monero-bin/monero-wallet-rpc --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log &
MONERO_WALLET_CLI_ALICE_PID=$! MONERO_WALLET_CLI_ALICE_PID=$!
# install ganache and run # install ganache-cli and run
echo "installing and starting ganache-cli..." GANACHE_EXEC="$(npm config get prefix)/bin/ganache-cli"
if ! command -v golangci-lint &> /dev/null; then if [[ ! -x "${GANACHE_EXEC}" ]]; then
npm i -g ganache-cli echo "installing ganache-cli"
npm install --location=global ganache-cli
fi fi
echo "starting ganache-cli"
export NODE_OPTIONS=--max_old_space_size=8192 export NODE_OPTIONS=--max_old_space_size=8192
ganache-cli -d &> ganache-cli.log & "${GANACHE_EXEC}" --deterministic --accounts=20 &> ganache-cli.log &
GANACHE_CLI_PID=$! GANACHE_CLI_PID=$!
# wait for servers to start # wait for servers to start
@@ -35,15 +38,15 @@ sleep 10
echo "starting alice, logs in ./tests/alice.log" echo "starting alice, logs in ./tests/alice.log"
bash scripts/build.sh bash scripts/build.sh
./swapd --dev-xmrtaker --libp2p-key=./tests/alice.key &> ./tests/alice.log & ./swapd --dev-xmrtaker --libp2p-key=./tests/alice.key &> ./tests/alice.log &
ALICE_PID=$! ALICE_SWAPD_PID=$!
sleep 3 sleep 3
echo "starting bob, logs in ./tests/bob.log" echo "starting bob, logs in ./tests/bob.log"
./swapd --dev-xmrmaker --bootnodes /ip4/127.0.0.1/tcp/9933/p2p/12D3KooWAYn1T8Lu122Pav4zAogjpeU61usLTNZpLRNh9gCqY6X2 --wallet-file test-wallet --deploy &> ./tests/bob.log & ./swapd --dev-xmrmaker --bootnodes /ip4/127.0.0.1/tcp/9933/p2p/12D3KooWAYn1T8Lu122Pav4zAogjpeU61usLTNZpLRNh9gCqY6X2 --wallet-file test-wallet --deploy &> ./tests/bob.log &
BOB_PID=$! BOB_SWAPD_PID=$!
sleep 3 sleep 3
echo "starting charlie, logs in ./tests/charlie.log" echo "starting charlie, logs in ./tests/charlie.log"
./swapd --libp2p-port 9955 --rpc-port 5003 --ws-port 8083 --bootnodes /ip4/127.0.0.1/tcp/9933/p2p/12D3KooWAYn1T8Lu122Pav4zAogjpeU61usLTNZpLRNh9gCqY6X2 --deploy &> ./tests/charlie.log & ./swapd --libp2p-port 9955 --rpc-port 5003 --ws-port 8083 --bootnodes /ip4/127.0.0.1/tcp/9933/p2p/12D3KooWAYn1T8Lu122Pav4zAogjpeU61usLTNZpLRNh9gCqY6X2 --deploy &> ./tests/charlie.log &
CHARLIE_PID=$! CHARLIE_SWAPD_PID=$!
sleep 3 sleep 3
# run tests # run tests
@@ -52,12 +55,12 @@ TESTS=integration go test ./tests -v
OK=$? OK=$?
# kill processes # kill processes
kill $MONERO_WALLET_CLI_BOB_PID kill "${MONERO_WALLET_CLI_BOB_PID}" || echo "Bob's wallet CLI was not running at end of test"
kill $MONERO_WALLET_CLI_ALICE_PID kill "${MONERO_WALLET_CLI_ALICE_PID}" || echo "Alice's wallet CLI was not running at end of test"
kill $GANACHE_CLI_PID kill "${GANACHE_CLI_PID}" || echo "ganache-cli was not running at end of test"
kill $ALICE_PID kill "${ALICE_SWAPD_PID}" || echo "Alice's swapd was not running at end of test"
kill $BOB_PID kill "${BOB_SWAPD_PID}" || echo "Bob's swapd was not running at end of test"
kill $CHARLIE_PID kill "${CHARLIE_SWAPD_PID}" || echo "Charlie's swapd was not running at end of test"
# rm -rf ./alice-test-keys # rm -rf ./alice-test-keys
# rm -rf ./bob-test-keys # rm -rf ./bob-test-keys
exit $OK exit $OK

View File

@@ -1,31 +1,20 @@
#!/bin/bash #!/bin/bash
# install monero and run daemon and wallet RPC servers for alice and bob # install monero and run daemon and wallet RPC servers for alice and bob
bash ./scripts/install-monero-linux.sh ./scripts/install-monero-linux.sh
echo "starting monerod..." echo "starting monerod..."
./monero-x86_64-linux-gnu-v0.17.3.2/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-port 18081 & ./monero-bin/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18081
sleep 5 sleep 5
echo "starting monero-wallet-rpc on port 18083..." # install ganache-cli and run
mkdir bob-test-keys GANACHE_EXEC="$(npm config get prefix)/bin/ganache-cli"
./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log & if [[ ! -x "${GANACHE_EXEC}" ]]; then
MONERO_WALLET_CLI_BOB_PID=$! echo "installing ganache-cli"
npm install --location=global ganache-cli
sleep 5
curl http://localhost:18083/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"test-wallet","password":"","language":"English"}}' -H 'Content-Type: application/json'
echo "starting monero-wallet-rpc on port 18084..."
mkdir alice-test-keys
./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log &
MONERO_WALLET_CLI_ALICE_PID=$!
# install ganache and run
echo "installing and starting ganache-cli..."
if ! command -v golangci-lint &> /dev/null; then
npm i -g ganache-cli
fi fi
echo "starting ganache-cli"
export NODE_OPTIONS=--max_old_space_size=8192 export NODE_OPTIONS=--max_old_space_size=8192
ganache-cli -d &> ganache-cli.log & "${GANACHE_EXEC}" --deterministic --accounts=20 &> ganache-cli.log &
GANACHE_CLI_PID=$! GANACHE_CLI_PID=$!
# wait for servers to start # wait for servers to start
@@ -37,9 +26,5 @@ go test ./... -v -short -timeout=30m -covermode=atomic -coverprofile=coverage.ou
OK=$? OK=$?
# kill processes # kill processes
kill $MONERO_WALLET_CLI_BOB_PID kill "${GANACHE_CLI_PID}" || echo "ganache-cli was not running at end of test"
kill $MONERO_WALLET_CLI_ALICE_PID exit $OK
kill $GANACHE_CLI_PID
# rm -rf ./alice-test-keys
# rm -rf ./bob-test-keys
exit $OK

View File

@@ -1,25 +1,25 @@
#!/bin/bash #!/bin/bash
# useful dir relative to this script # useful dir relative to this script
MONERO_DIR="../monero-x86_64-linux-gnu-v0.17.3.0" MONERO_DIR="../monero-bin"
# either a TMPDIR is set, or use /tmp # either a TMPDIR is set, or use /tmp
LOG_DIR=${TMPDIR:-"/tmp"} LOG_DIR=${TMPDIR:-"/tmp"}
ALICE_P2P_ADDRESS="12D3KooWBD82zGTFqk6Qmu5zeS6dQfiaAcn8go2QWE29HPmRX3yB" ALICE_P2P_ADDRESS="12D3KooWBD82zGTFqk6Qmu5zeS6dQfiaAcn8go2QWE29HPmRX3yB"
echo "cleanup" echo "cleanup"
pkill -e -f monero; pkill -e -f monero
pkill -e -f ganache-cli; pkill -e -f ganache-cli
killall -v swapd; killall -v swapd
pkill -e -f swapcli; pkill -e -f swapcli
echo "start ganache-cli" echo "start ganache-cli"
ganache-cli -d &> $LOG_DIR/ganache-cli.log & "$(npm config get prefix)/bin/ganache-cli" --deterministic --accounts=20 &> "${LOG_DIR}/ganache-cli.log" &
echo "move to $MONERO_DIR" echo "move to $MONERO_DIR"
cd $MONERO_DIR cd "${MONERO_DIR}"
echo "starting monerod..." echo "starting monerod..."
./monerod --regtest --detach --fixed-difficulty=1 --rpc-bind-port 18081 --offline &> $LOG_DIR/monerod.log & ./monerod --regtest --detach --fixed-difficulty=1 --rpc-bind-port 18081 --offline &> "${LOG_DIR}/monerod.log" &
echo "Zzz... 10s" echo "Zzz... 10s"
sleep 10 sleep 10
@@ -31,19 +31,19 @@ echo "Zzz... 15s"
sleep 15 sleep 15
echo "start monero-wallet-rpc for XMRTaker on port 18084" echo "start monero-wallet-rpc for XMRTaker on port 18084"
./monero-wallet-rpc --rpc-bind-port 18084 --password "" --disable-rpc-login --wallet-dir . &> $LOG_DIR/alice-wallet-rpc.log & ./monero-wallet-rpc --rpc-bind-port 18084 --password "" --disable-rpc-login --wallet-dir . &> "${LOG_DIR}/alice-wallet-rpc.log" &
echo "start monero-wallet-rpc for XMRMaker on port 18083" echo "start monero-wallet-rpc for XMRMaker on port 18083"
./monero-wallet-rpc --rpc-bind-port 18083 --password "" --disable-rpc-login --wallet-dir . &> $LOG_DIR/bob-wallet-rpc.log & ./monero-wallet-rpc --rpc-bind-port 18083 --password "" --disable-rpc-login --wallet-dir . &> "${LOG_DIR}/bob-wallet-rpc.log" &
echo "launch XMRTaker swapd" echo "launch XMRTaker swapd"
../swapd --dev-xmrtaker --external-signer --contract-address 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab &> $LOG_DIR/alice-swapd.log & ../swapd --dev-xmrtaker --external-signer --contract-address 0xe78A0F7E598Cc8b0Bb87894B0F60dD2a88d6a8Ab &> "${LOG_DIR}/alice-swapd.log" &
echo "Zzz... 10s" echo "Zzz... 10s"
sleep 10 sleep 10
echo "launch XMRMaker swapd" echo "launch XMRMaker swapd"
../swapd --dev-xmrmaker --wallet-file XMRMaker --bootnodes /ip4/127.0.0.1/tcp/9933/p2p/$ALICE_P2P_ADDRESS &> $LOG_DIR/bob-swapd.log & ../swapd --dev-xmrmaker --wallet-file XMRMaker --bootnodes "/ip4/127.0.0.1/tcp/9933/p2p/${ALICE_P2P_ADDRESS}" &> "${LOG_DIR}/bob-swapd.log" &
echo "Zzz... 10s" echo "Zzz... 10s"
sleep 10 sleep 10

View File

@@ -1,31 +1,34 @@
#!/bin/bash #!/bin/bash
# install monero and run daemon and wallet RPC servers for alice and bob # install monero and run daemon and wallet RPC servers for alice and bob
bash ./scripts/install-monero-linux.sh ./scripts/install-monero-linux.sh
echo "starting monerod..." echo "starting monerod..."
./monero-x86_64-linux-gnu-v0.17.3.0/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-port 18081 --keep-fakechain & ./monero-bin/monerod --detach --regtest --offline --fixed-difficulty=1 --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18081 --keep-fakechain
sleep 5 sleep 5
echo "starting monero-wallet-rpc on port 18083..." echo "starting monero-wallet-rpc on port 18083..."
mkdir bob-test-keys mkdir -p bob-test-keys
./monero-x86_64-linux-gnu-v0.17.3.0/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log & ./monero-bin/monero-wallet-rpc --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys &> monero-wallet-cli-bob.log &
MONERO_WALLET_CLI_BOB_PID=$! MONERO_WALLET_CLI_BOB_PID=$!
sleep 5 sleep 5
curl http://localhost:18083/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"test-wallet","password":"","language":"English"}}' -H 'Content-Type: application/json' curl http://localhost:18083/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"create_wallet","params":{"filename":"test-wallet","password":"","language":"English"}}' -H 'Content-Type: application/json'
echo
echo "starting monero-wallet-rpc on port 18084..." echo "starting monero-wallet-rpc on port 18084..."
mkdir alice-test-keys mkdir -p alice-test-keys
./monero-x86_64-linux-gnu-v0.17.3.0/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log & ./monero-bin/monero-wallet-rpc --rpc-bind-ip 127.0.0.1 --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys &> monero-wallet-cli-alice.log &
MONERO_WALLET_CLI_ALICE_PID=$! MONERO_WALLET_CLI_ALICE_PID=$!
# install ganache and run # install ganache-cli and run
echo "installing and starting ganache-cli..." GANACHE_EXEC="$(npm config get prefix)/bin/ganache-cli"
if ! command -v golangci-lint &> /dev/null; then if [[ ! -x "${GANACHE_EXEC}" ]]; then
npm i -g ganache-cli echo "installing ganache-cli"
npm install --location=global ganache-cli
fi fi
echo "starting ganache-cli"
export NODE_OPTIONS=--max_old_space_size=8192 export NODE_OPTIONS=--max_old_space_size=8192
ganache-cli -d &> ganache-cli.log & "${GANACHE_EXEC}" --deterministic --accounts=20 &> ganache-cli.log &
GANACHE_CLI_PID=$! GANACHE_CLI_PID=$!
# wait for servers to start # wait for servers to start

View File

@@ -2,14 +2,15 @@
bash ./scripts/install-monero-linux.sh bash ./scripts/install-monero-linux.sh
echo "starting monerod..." echo "starting monerod..."
nohup ./monero-x86_64-linux-gnu-v0.17.3.2/monerod --detach --stagenet --rpc-bind-port 18081 &
./monero-bin/monerod --detach --stagenet --rpc-bind-port 18081 &
sleep 5 sleep 5
echo "starting monero-wallet-rpc on port 18083..." echo "starting monero-wallet-rpc on port 18083..."
nohup ./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys --stagenet --trusted-daemon nohup ./monero-bin/monero-wallet-rpc --rpc-bind-port 18083 --disable-rpc-login --wallet-dir ./bob-test-keys --stagenet --trusted-daemon
echo "starting monero-wallet-rpc on port 18084..." echo "starting monero-wallet-rpc on port 18084..."
nohup ./monero-x86_64-linux-gnu-v0.17.3.2/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys --stagenet --trusted-daemon nohup ./monero-bin/monero-wallet-rpc --rpc-bind-port 18084 --disable-rpc-login --wallet-dir ./alice-test-keys --stagenet --trusted-daemon
# open Bob's wallet (must have funds) # open Bob's wallet (must have funds)
sleep 5 sleep 5

View File

@@ -17,6 +17,7 @@ import (
"github.com/noot/atomic-swap/common" "github.com/noot/atomic-swap/common"
"github.com/noot/atomic-swap/crypto/secp256k1" "github.com/noot/atomic-swap/crypto/secp256k1"
"github.com/noot/atomic-swap/dleq" "github.com/noot/atomic-swap/dleq"
"github.com/noot/atomic-swap/tests"
) )
var defaultTimeoutDuration = big.NewInt(60) // 60 seconds var defaultTimeoutDuration = big.NewInt(60) // 60 seconds
@@ -24,7 +25,7 @@ var defaultTimeoutDuration = big.NewInt(60) // 60 seconds
func setupXMRTakerAuth(t *testing.T) (*bind.TransactOpts, *ethclient.Client, *ecdsa.PrivateKey) { func setupXMRTakerAuth(t *testing.T) (*bind.TransactOpts, *ethclient.Client, *ecdsa.PrivateKey) {
conn, err := ethclient.Dial(common.DefaultEthEndpoint) conn, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err) require.NoError(t, err)
pkA, err := crypto.HexToECDSA(common.DefaultPrivKeyXMRTaker) pkA, err := crypto.HexToECDSA(tests.GetTakerTestKey(t))
require.NoError(t, err) require.NoError(t, err)
auth, err := bind.NewKeyedTransactorWithChainID(pkA, big.NewInt(common.GanacheChainID)) auth, err := bind.NewKeyedTransactorWithChainID(pkA, big.NewInt(common.GanacheChainID))
require.NoError(t, err) require.NoError(t, err)
@@ -33,6 +34,7 @@ func setupXMRTakerAuth(t *testing.T) (*bind.TransactOpts, *ethclient.Client, *ec
func TestSwapFactory_NewSwap(t *testing.T) { func TestSwapFactory_NewSwap(t *testing.T) {
auth, conn, _ := setupXMRTakerAuth(t) auth, conn, _ := setupXMRTakerAuth(t)
defer conn.Close()
address, tx, contract, err := DeploySwapFactory(auth, conn) address, tx, contract, err := DeploySwapFactory(auth, conn)
require.NoError(t, err) require.NoError(t, err)
require.NotEqual(t, ethcommon.Address{}, address) require.NotEqual(t, ethcommon.Address{}, address)
@@ -65,6 +67,7 @@ func TestSwapFactory_Claim_vec(t *testing.T) {
// deploy swap contract with claim key hash // deploy swap contract with claim key hash
auth, conn, pkA := setupXMRTakerAuth(t) auth, conn, pkA := setupXMRTakerAuth(t)
defer conn.Close()
pub := pkA.Public().(*ecdsa.PublicKey) pub := pkA.Public().(*ecdsa.PublicKey)
addr := crypto.PubkeyToAddress(*pub) addr := crypto.PubkeyToAddress(*pub)
@@ -200,6 +203,7 @@ func TestSwap_Refund_beforeT0(t *testing.T) {
// deploy swap contract with refund key hash // deploy swap contract with refund key hash
auth, conn, pkA := setupXMRTakerAuth(t) auth, conn, pkA := setupXMRTakerAuth(t)
defer conn.Close()
pub := pkA.Public().(*ecdsa.PublicKey) pub := pkA.Public().(*ecdsa.PublicKey)
addr := crypto.PubkeyToAddress(*pub) addr := crypto.PubkeyToAddress(*pub)
@@ -264,6 +268,7 @@ func TestSwap_Refund_afterT1(t *testing.T) {
// deploy swap contract with refund key hash // deploy swap contract with refund key hash
auth, conn, pkA := setupXMRTakerAuth(t) auth, conn, pkA := setupXMRTakerAuth(t)
defer conn.Close()
pub := pkA.Public().(*ecdsa.PublicKey) pub := pkA.Public().(*ecdsa.PublicKey)
addr := crypto.PubkeyToAddress(*pub) addr := crypto.PubkeyToAddress(*pub)
@@ -335,6 +340,7 @@ func TestSwap_Refund_afterT1(t *testing.T) {
func TestSwap_MultipleSwaps(t *testing.T) { func TestSwap_MultipleSwaps(t *testing.T) {
// test case where contract has multiple swaps happening at once // test case where contract has multiple swaps happening at once
auth, conn, pkA := setupXMRTakerAuth(t) auth, conn, pkA := setupXMRTakerAuth(t)
defer conn.Close()
pub := pkA.Public().(*ecdsa.PublicKey) pub := pkA.Public().(*ecdsa.PublicKey)
addr := crypto.PubkeyToAddress(*pub) addr := crypto.PubkeyToAddress(*pub)

103
tests/ganache_test_keys.go Normal file
View File

@@ -0,0 +1,103 @@
package tests
import (
"runtime"
"strings"
"testing"
)
/*
* Golang packages can be tested in parallel, but in our case, they are sharing a
* common ganache Ethereum simulator. To avoid transaction conflicts, we allocate
* each package listed in `testPackageNames` below 2 keys. One taker and one maker
* (or however the package chooses to use the keys). When different packages are tested
* in parallel, there is no shared global state, so we can't use any kind of pool or
* non-deterministic map traversals.
*/
// testPackageNames is the list of packages with _test.go code that requires access to
// one or more prefunded ganache wallets.
var testPackageNames = []string{
"cmd/daemon",
"protocol/backend",
"protocol/xmrmaker",
"protocol/xmrtaker",
"recover",
"swapfactory",
}
const (
ethKeysPerPackage = 2
repoName = "github.com/noot/atomic-swap/"
)
// `ganache-cli --deterministic --accounts=20` provides the following keys with
// 100 ETH on startup. The first 2 keys can be found in const.go and reserved
// for use in non-test files (files without the _test.go suffix).
var ganacheTestKeys = []string{
"6370fd033278c143179d81c5526140625662b8daa446c22ee2d73db3707e620c", // ganache key #2
"646f1ce2fdad0e6deeeb5c7e8e5543bdde65e86029e2fd9fc169899c440a7913", // ganache key #3
"add53f9a7e588d003326d1cbf9e4a43c061aadd9bc938c843a79e7b4fd2ad743", // ganache key #4
"395df67f0c2d2d9fe1ad08d1bc8b6627011959b79c53d7dd6a3536a33ab8a4fd", // ganache key #5
"e485d098507f54e7733a205420dfddbe58db035fa577fc294ebd14db90767a52", // ganache key #6
"a453611d9419d0e56f499079478fd72c37b251a94bfde4d19872c44cf65386e3", // ganache key #7
"829e924fdf021ba3dbbc4225edfece9aca04b929d6e75613329ca6f1d31c0bb4", // ganache key #8
"b0057716d5917badaf911b193b12b910811c1497b5bada8d7711f758981c3773", // ganache key #9
"77c5495fbb039eed474fc940f29955ed0531693cc9212911efd35dff0373153f", // ganache key #10
"d99b5b29e6da2528bf458b26237a6cf8655a3e3276c1cdc0de1f98cefee81c01", // ganache key #11
"9b9c613a36396172eab2d34d72331c8ca83a358781883a535d2941f66db07b24", // ganache key #12
"0874049f95d55fb76916262dc70571701b5c4cc5900c0691af75f1a8a52c8268", // ganache key #13
"21d7212f3b4e5332fd465877b64926e3532653e2798a11255a46f533852dfe46", // ganache key #14
"47b65307d0d654fd4f786b908c04af8fface7710fc998b37d219de19c39ee58c", // ganache key #15
"66109972a14d82dbdb6894e61f74708f26128814b3359b64f8b66565679f7299", // ganache key #16
"2eac15546def97adc6d69ca6e28eec831189baa2533e7910755d15403a0749e8", // ganache key #17
"2e114163041d2fb8d45f9251db259a68ee6bdbfd6d10fe1ae87c5c4bcd6ba491", // ganache key #18
"ae9a2e131e9b359b198fa280de53ddbe2247730b881faae7af08e567e58915bd", // ganache key #19
}
func init() {
if len(testPackageNames)*ethKeysPerPackage > len(ganacheTestKeys) {
panic("Insufficient ganache test keys")
}
}
// minPackageName takes a long-form package+function name (example:
// "github.com/noot/atomic-swap/protocol/xmrtaker.newBackend") and returns
// just the package name without the repository prefix ("protocol/xmrtaker").
func minPackageName(t *testing.T, pkgAndFunc string) string {
minPkgAndFunc := strings.TrimPrefix(pkgAndFunc, repoName)
if minPkgAndFunc == pkgAndFunc {
t.Fatalf("%q does not have the repo prefix %q", pkgAndFunc, repoName)
}
// with the domain name gone, the minimal package is everything before the first period.
return strings.Split(minPkgAndFunc, ".")[0]
}
func getPackageIndex(t *testing.T) uint {
// Determine the test package that requested the key from the call stack
pc, _, _, ok := runtime.Caller(2) // skipping this function and GetMakerTestKey/GetTakerTestKey
if !ok {
t.Fatalf("Failed to get caller info")
}
// returns the package and function name from the program counter
// example: "github.com/noot/atomic-swap/protocol/xmrtaker.newBackend"
packageName := minPackageName(t, runtime.FuncForPC(pc).Name())
for i, name := range testPackageNames {
if name == packageName {
return uint(i)
}
}
t.Fatalf("Package %q does not have reserved test keys", packageName)
panic("unreachable code")
}
// GetMakerTestKey returns a unique Ethereum/ganache maker key per test package
func GetMakerTestKey(t *testing.T) string {
return ganacheTestKeys[getPackageIndex(t)*ethKeysPerPackage]
}
// GetTakerTestKey returns a unique Ethereum/ganache taker key per test package
func GetTakerTestKey(t *testing.T) string {
return ganacheTestKeys[getPackageIndex(t)*ethKeysPerPackage+1]
}

View File

@@ -0,0 +1,89 @@
package tests
import (
"bufio"
"fmt"
"net"
"os/exec"
"path"
"runtime"
"strings"
"testing"
"github.com/stretchr/testify/require"
)
// CreateWalletRPCService starts a monero-wallet-rpc listening on a random port for tests. The json_rpc
// URL of the started service is returned.
func CreateWalletRPCService(t *testing.T) string {
port := getFreePort(t)
walletRPCBin := getMoneroWalletRPCBin(t)
walletRPCBinArgs := getWalletRPCFlags(t, port)
cmd := exec.Command(walletRPCBin, walletRPCBinArgs...)
outPipe, err := cmd.StdoutPipe()
require.NoError(t, err)
err = cmd.Start()
require.NoError(t, err)
t.Cleanup(func() {
_ = outPipe.Close()
_ = cmd.Process.Kill()
})
scanner := bufio.NewScanner(outPipe)
started := false
for scanner.Scan() {
line := scanner.Text()
//t.Log(line)
if strings.HasSuffix(line, "Starting wallet RPC server") {
started = true
break
}
}
if !started {
t.Fatal("failed to start monero-wallet-rpc")
}
// drain any additional output
go func() {
for scanner.Scan() {
//t.Log(scanner.Text())
}
}()
require.NoError(t, err)
return fmt.Sprintf("http://127.0.0.1:%d/json_rpc", port)
}
// getMoneroWalletRPCBin returns the monero-wallet-rpc binary assuming it was
// installed at the top of the repo in a directory named "monero-bin".
func getMoneroWalletRPCBin(t *testing.T) string {
_, filename, _, ok := runtime.Caller(0) // this test file path
require.True(t, ok)
packageDir := path.Dir(filename)
repoBaseDir := path.Dir(packageDir)
return path.Join(repoBaseDir, "monero-bin", "monero-wallet-rpc")
}
// getWalletRPCFlags returns the flags used when launching monero-wallet-rpc in a temporary
// test folder.
func getWalletRPCFlags(t *testing.T, port int) []string {
walletDir := t.TempDir()
return []string{
"--rpc-bind-ip=127.0.0.1",
fmt.Sprintf("--rpc-bind-port=%d", port),
"--disable-rpc-login",
fmt.Sprintf("--log-file=%s", path.Join(walletDir, "monero-wallet-rpc.log")),
fmt.Sprintf("--wallet-dir=%s", t.TempDir()),
}
}
// getFreePort returns an OS allocated and immediately freed port. There is nothing preventing
// something else on the system from using the port before the caller has a chance, but OS
// allocated ports are randomised to minimise this risk.
func getFreePort(t *testing.T) int {
ln, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
port := ln.Addr().(*net.TCPAddr).Port
require.NoError(t, ln.Close())
return port
}