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
# Monero dir
monero.tar.bz2
/monero-x86*
/monero.tar.bz2
/monero-*
# bin
swapcli
@@ -52,4 +52,4 @@ Cargo.lock
*.key
log
*.log
*.log

View File

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

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"math/big"
"path"
"github.com/noot/atomic-swap/common"
pcommon "github.com/noot/atomic-swap/protocol"
@@ -20,7 +21,7 @@ var (
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) {
var (
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())
// 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 {
return nil, ethcommon.Address{}, fmt.Errorf("failed to write contract address to file: %w", err)
}

View File

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

View File

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

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
logging "github.com/ipfs/go-log"
"github.com/urfave/cli"
@@ -28,19 +29,14 @@ var (
// GetEthereumPrivateKey returns an ethereum private key hex string given the CLI options.
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) != "" {
ethPrivKeyFile := c.String(flagEthereumPrivKey)
key, err := os.ReadFile(filepath.Clean(ethPrivKeyFile))
if err != nil {
return "", fmt.Errorf("failed to read ethereum-privkey file: %w", err)
}
if key[len(key)-1] == '\n' {
key = key[:len(key)-1]
}
ethPrivKey = string(key)
ethPrivKeyHex = strings.TrimSpace(string(key))
} else {
if env != common.Development || useExternal {
// 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")
if devXMRMaker {
ethPrivKey = common.DefaultPrivKeyXMRMaker
ethPrivKeyHex = common.DefaultPrivKeyXMRMaker
} else {
ethPrivKey = common.DefaultPrivKeyXMRTaker
ethPrivKeyHex = common.DefaultPrivKeyXMRTaker
}
}
return ethPrivKey, nil
return ethPrivKeyHex, nil
}
// 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"
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"
// 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"
)

View File

@@ -90,7 +90,7 @@ type FarcasterDLEq struct{}
// Prove generates a new DLEq proof
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)
cmd := exec.Command(dleqGenBinPath, path)
@@ -119,7 +119,7 @@ func (d *FarcasterDLEq) Prove() (*Proof, error) {
// Verify verifies a DLEq proof
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)
if err := ioutil.WriteFile(path, p.proof, os.ModePerm); err != nil {

View File

@@ -1,11 +1,17 @@
# 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
wget https://go.dev/dl/go1.18.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.18.linux-amd64.tar.gz
sudo snap install go --classic
```
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
source .profile
```
@@ -21,4 +27,4 @@ cd atomic-swap
make build
```
This creates the binaries `swapd` and `swapcli`.
This creates the binaries `swapd` and `swapcli`.

View File

@@ -3,23 +3,29 @@
### Requirements
- 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
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
ganache-cli -d
ganache-cli --deterministic --accounts=20
```
Start monerod for regtest, this binary is in the monero bin directory:
```bash
cd ./monero-x86_64-linux-gnu
./monerod --regtest --fixed-difficulty=1 --rpc-bind-port 18081 --offline
cd ./monero-bin
./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:
@@ -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:
```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:
@@ -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):
```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

View File

@@ -1,14 +1,13 @@
package monero
import (
"crypto/rand"
"fmt"
"math/big"
"testing"
"time"
"github.com/noot/atomic-swap/common"
mcrypto "github.com/noot/atomic-swap/crypto/monero"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require"
)
@@ -19,16 +18,16 @@ func TestClient_Transfer(t *testing.T) {
}
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)
xmrmakerAddr, err := cXMRMaker.callGetAddress(0)
require.NoError(t, err)
daemon := NewClient(common.DefaultMoneroDaemonEndpoint)
_ = daemon.callGenerateBlocks(xmrmakerAddr.Address, 181)
_ = daemon.callGenerateBlocks(xmrmakerAddr.Address, 512)
time.Sleep(time.Second * 10)
@@ -51,13 +50,10 @@ func TestClient_Transfer(t *testing.T) {
kpABPub := mcrypto.SumSpendAndViewKeys(kpA.PublicKeyPair(), kpB.PublicKeyPair())
vkABPriv := mcrypto.SumPrivateViewKeys(kpA.ViewKey(), kpB.ViewKey())
r, err := rand.Int(rand.Reader, big.NewInt(10000))
require.NoError(t, err)
cXMRTaker := NewClient(common.DefaultXMRTakerMoneroEndpoint)
cXMRTaker := NewClient(tests.CreateWalletRPCService(t))
// 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, "")
require.NoError(t, err)
err = cXMRTaker.OpenWallet(walletFP, "")
@@ -84,20 +80,20 @@ func TestClient_Transfer(t *testing.T) {
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
skAKPriv := mcrypto.SumPrivateSpendKeys(kpA.SpendKey(), kpB.SpendKey())
// ignore the error for now, as it can error with "Wallet already exists."
_ = cXMRTaker.callGenerateFromKeys(skAKPriv, vkABPriv, kpABPub.Address(common.Mainnet),
fmt.Sprintf("test-wallet-%d", r), "")
_ = cXMRTaker.callGenerateFromKeys(skAKPriv, vkABPriv, kpABPub.Address(common.Mainnet), walletFP, "")
err = cXMRTaker.refresh()
require.NoError(t, err)
balance, err = cXMRTaker.GetBalance(0)
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
_, 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) {
c := NewClient(common.DefaultXMRMakerMoneroEndpoint)
err := c.OpenWallet("test-wallet", "")
c := NewClient(tests.CreateWalletRPCService(t))
err := c.CreateWallet("test-wallet", "")
require.NoError(t, err)
err = c.CloseWallet()
@@ -117,14 +113,18 @@ func TestClient_CloseWallet(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()
require.NoError(t, err)
require.Equal(t, 1, len(resp.SubaddressAccounts))
}
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()
require.NoError(t, err)
require.NotEqual(t, 0, resp)

View File

@@ -8,6 +8,7 @@ import (
"github.com/noot/atomic-swap/common"
mcrypto "github.com/noot/atomic-swap/crypto/monero"
"github.com/noot/atomic-swap/tests"
"github.com/stretchr/testify/require"
)
@@ -19,7 +20,7 @@ func TestCallGenerateFromKeys(t *testing.T) {
r, err := rand.Int(rand.Reader, big.NewInt(999))
require.NoError(t, err)
c := NewClient(common.DefaultXMRMakerMoneroEndpoint)
c := NewClient(tests.CreateWalletRPCService(t))
err = c.callGenerateFromKeys(kp.SpendKey(), kp.ViewKey(), kp.Address(common.Mainnet),
fmt.Sprintf("test-wallet-%d", r), "")
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.
func CreateMoneroWallet(name string, env common.Environment, client Client,
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)
if err := client.GenerateFromKeys(kpAB, walletName, "", env); err != nil {
return "", err

View File

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

View File

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

View File

@@ -134,7 +134,7 @@ func (m *QueryResponse) Type() Type {
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.
// SendKeysMessage is sent by both parties to each other to initiate the protocol

View File

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

View File

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

View File

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

View File

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

View File

@@ -149,7 +149,7 @@ func (s *swapState) handleNotifyETHLocked(msg *message.NotifyETHLocked) (net.Mes
s.contractSwapID = msg.ContractSwapID
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
}
@@ -162,7 +162,7 @@ func (s *swapState) handleNotifyETHLocked(msg *message.NotifyETHLocked) (net.Mes
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)
}

View File

@@ -19,7 +19,7 @@ type recoveryState struct {
// NewRecoveryState returns a new *xmrmaker.recoveryState,
// 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,
contractSwapID [32]byte, contractSwap swapfactory.SwapFactorySwap) (*recoveryState, error) { //nolint:revive
kp, err := secret.AsPrivateKeyPair()
@@ -42,7 +42,7 @@ func NewRecoveryState(b backend.Backend, basepath string, secret *mcrypto.Privat
dleqProof: dleq.NewProofWithSecret(sc),
contractSwapID: contractSwapID,
contractSwap: contractSwap,
infofile: pcommon.GetSwapRecoveryFilepath(basepath),
infoFile: pcommon.GetSwapRecoveryFilepath(basePath),
}
if err := s.setContract(contractAddr); err != nil {

View File

@@ -2,6 +2,7 @@ package xmrmaker
import (
"math/big"
"path"
"testing"
"time"
@@ -23,7 +24,8 @@ func newTestRecoveryState(t *testing.T) *recoveryState {
require.NoError(t, err)
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)
require.NoError(t, err)

View File

@@ -43,7 +43,7 @@ type swapState struct {
ctx context.Context
cancel context.CancelFunc
sync.Mutex
infofile string
infoFile string
info *pswap.Info
offer *types.Offer
@@ -77,7 +77,7 @@ type swapState struct {
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) {
exchangeRate := types.ExchangeRate(providesAmount.AsMonero() / desiredAmount.AsEther())
stage := types.ExpectingKeys
@@ -98,7 +98,7 @@ func newSwapState(b backend.Backend, offer *types.Offer, om *offerManager, statu
Backend: b,
offer: offer,
offerManager: om,
infofile: infofile,
infoFile: infoFile,
nextExpectedMessage: &net.SendKeysMessage{},
readyCh: make(chan struct{}),
info: info,
@@ -125,9 +125,9 @@ func (s *swapState) SendKeysMessage() (*net.SendKeysMessage, error) {
}, nil
}
// InfoFile returns the swap's infofile path
// InfoFile returns the swap's infoFile path
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
@@ -261,7 +261,7 @@ func (s *swapState) reclaimMonero(skA *mcrypto.PrivateSpendKey) (mcrypto.Address
kpAB := mcrypto.NewPrivateKeyPair(skAB, vkAB)
// 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
}
@@ -361,7 +361,7 @@ func (s *swapState) generateAndSetKeys() error {
s.privkeys = keysAndProof.PrivateKeyPair
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) {

View File

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

View File

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

View File

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

View File

@@ -216,7 +216,7 @@ func (s *swapState) handleNotifyXMRLock(msg *message.NotifyXMRLock) (net.Message
s.LockClient()
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)
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)

View File

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

View File

@@ -25,7 +25,7 @@ type recoveryState struct {
// NewRecoveryState returns a new *xmrmaker.recoveryState,
// 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
kp, err := secret.AsPrivateKeyPair()
if err != nil {
@@ -47,7 +47,7 @@ func NewRecoveryState(b backend.Backend, basepath string, secret *mcrypto.Privat
dleqProof: dleq.NewProofWithSecret(sc),
contractSwapID: contractSwapID,
contractSwap: contractSwap,
infofile: pcommon.GetSwapRecoveryFilepath(basepath),
infoFile: pcommon.GetSwapRecoveryFilepath(basePath),
claimedCh: make(chan struct{}),
}
@@ -68,8 +68,7 @@ type RecoveryResult struct {
MoneroAddress mcrypto.Address
}
// ClaimOrRecover either claims ether or recovers monero by creating a wallet.
// It returns a *RecoveryResult.
// ClaimOrRefund either claims the monero or recovers the ether returning a *RecoveryResult.
func (rs *recoveryState) ClaimOrRefund() (*RecoveryResult, error) {
// check if XMRMaker claimed
skA, err := rs.ss.filterForClaim()

View File

@@ -1,6 +1,7 @@
package xmrtaker
import (
"path"
"testing"
"time"
@@ -27,7 +28,8 @@ func newTestRecoveryState(t *testing.T) *recoveryState {
_, err = s.lockETH(common.NewEtherAmount(1))
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)
return rs
}

View File

@@ -36,7 +36,7 @@ type swapState struct {
ctx context.Context
cancel context.CancelFunc
sync.Mutex
infofile string
infoFile string
transferBack bool
info *pswap.Info
@@ -99,7 +99,7 @@ func newSwapState(b backend.Backend, offerID types.Hash, infofile string, transf
ctx: ctx,
cancel: cancel,
Backend: b,
infofile: infofile,
infoFile: infofile,
transferBack: transferBack,
nextExpectedMessage: &net.SendKeysMessage{},
xmrLockedCh: make(chan struct{}),
@@ -109,7 +109,7 @@ func newSwapState(b backend.Backend, offerID types.Hash, infofile string, transf
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)
}
@@ -149,9 +149,9 @@ func (s *swapState) SendKeysMessage() (*net.SendKeysMessage, error) {
}, nil
}
// InfoFile returns the swap's infofile path
// InfoFile returns the swap's infoFile path
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
@@ -344,7 +344,7 @@ func (s *swapState) generateAndSetKeys() error {
s.privkeys = keysAndProof.PrivateKeyPair
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,
@@ -419,7 +419,7 @@ func (s *swapState) lockETH(amount common.EtherAmount) (ethcommon.Hash, error) {
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
}
@@ -472,7 +472,7 @@ func (s *swapState) claimMonero(skB *mcrypto.PrivateSpendKey) (mcrypto.Address,
kpAB := mcrypto.NewPrivateKeyPair(skAB, vkAB)
// 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
}

View File

@@ -21,6 +21,7 @@ import (
"github.com/noot/atomic-swap/protocol/backend"
pswap "github.com/noot/atomic-swap/protocol/swap"
"github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
logging "github.com/ipfs/go-log"
"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 {
pk, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRTaker)
pk, err := ethcrypto.HexToECDSA(tests.GetTakerTestKey(t))
require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint)
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)
addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec)
require.NoError(t, err)
bcfg := &backend.Config{
Ctx: context.Background(),
MoneroWalletEndpoint: common.DefaultXMRTakerMoneroEndpoint,
MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
EthereumClient: ec,
EthereumPrivateKey: pk,
Environment: common.Development,
ChainID: big.NewInt(common.MainnetConfig.EthereumChainID),
ChainID: big.NewInt(common.DevelopmentConfig.EthereumChainID),
SwapManager: pswap.NewManager(),
SwapContract: contract,
SwapContractAddress: addr,
@@ -71,25 +75,26 @@ func newBackend(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)
ec, err := ethclient.Dial(common.DefaultEthEndpoint)
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)
addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec)
require.NoError(t, err)
bcfg := &backend.Config{
Ctx: context.Background(),
MoneroWalletEndpoint: common.DefaultXMRMakerMoneroEndpoint,
MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
EthereumClient: ec,
EthereumPrivateKey: pk,
Environment: common.Development,
ChainID: big.NewInt(common.MainnetConfig.EthereumChainID),
ChainID: big.NewInt(common.DevelopmentConfig.EthereumChainID),
SwapManager: pswap.NewManager(),
SwapContract: contract,
SwapContractAddress: addr,
@@ -278,7 +283,7 @@ func TestSwapState_NotifyClaimed(t *testing.T) {
// close swap-deposit-wallet
maker := newXMRMakerBackend(t)
err := maker.OpenWallet("test-wallet", "")
err := maker.CreateWallet("test-wallet", "")
require.NoError(t, err)
// invalid SendKeysMessage should result in an error
@@ -308,7 +313,10 @@ func TestSwapState_NotifyClaimed(t *testing.T) {
require.NoError(t, err)
// 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)
kp := mcrypto.SumSpendAndViewKeys(s.pubkeys, s.pubkeys)
xmrAddr := kp.Address(common.Mainnet)
@@ -331,7 +339,7 @@ func TestSwapState_NotifyClaimed(t *testing.T) {
require.NotNil(t, resp)
require.Equal(t, message.NotifyReadyType, resp.Type())
_ = maker.GenerateBlocks(xmrmakerAddr.Address, 1)
err = maker.GenerateBlocks(xmrmakerAddr.Address, 1)
require.NoError(t, err)
// 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.
func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, basepath string,
func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, basePath string,
xmrmakerSecret, contractAddr string, swapID [32]byte,
swap swapfactory.SwapFactorySwap) (*xmrmaker.RecoveryResult, error) {
bs, err := hex.DecodeString(xmrmakerSecret)
@@ -103,7 +103,7 @@ func (r *recoverer) RecoverFromXMRMakerSecretAndContract(b backend.Backend, base
}
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 {
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.
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) {
as, err := hex.DecodeString(xmrtakerSecret)
if err != nil {
@@ -124,7 +124,7 @@ func (r *recoverer) RecoverFromXMRTakerSecretAndContract(b backend.Backend, base
return nil, err
}
rs, err := xmrtaker.NewRecoveryState(b, basepath, ak, swapID, swap)
rs, err := xmrtaker.NewRecoveryState(b, basePath, ak, swapID, swap)
if err != nil {
return nil, err
}

View File

@@ -3,6 +3,7 @@ package recovery
import (
"context"
"math/big"
"path"
"testing"
"github.com/noot/atomic-swap/common"
@@ -10,6 +11,7 @@ import (
pcommon "github.com/noot/atomic-swap/protocol"
"github.com/noot/atomic-swap/protocol/backend"
"github.com/noot/atomic-swap/swapfactory"
"github.com/noot/atomic-swap/tests"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
ethcommon "github.com/ethereum/go-ethereum/common"
@@ -18,19 +20,28 @@ import (
"github.com/stretchr/testify/require"
)
var defaulTimeout int64 = 5 // 5 seconds
var defaultTimeout int64 = 5 // 5 seconds
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)
return r
}
func newSwap(t *testing.T, claimKey, refundKey [32]byte,
setReady bool) (ethcommon.Address, *swapfactory.SwapFactory, [32]byte, swapfactory.SwapFactorySwap) {
tm := big.NewInt(defaulTimeout)
func newSwap(
t *testing.T,
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)
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)
require.NoError(t, err)
t.Cleanup(func() {
ec.Close()
})
addr, _, contract, err := swapfactory.DeploySwapFactory(txOpts, ec)
require.NoError(t, err)
pkXMRMaker, err := ethcrypto.HexToECDSA(common.DefaultPrivKeyXMRMaker)
pkXMRMaker, err := ethcrypto.HexToECDSA(tests.GetMakerTestKey(t))
require.NoError(t, err)
nonce := big.NewInt(0)
@@ -79,13 +93,20 @@ func newSwap(t *testing.T, claimKey, refundKey [32]byte,
return addr, contract, swapID, swap
}
func newBackend(t *testing.T, addr ethcommon.Address, contract *swapfactory.SwapFactory,
privkey string) backend.Backend {
func newBackend(
t *testing.T,
addr ethcommon.Address,
contract *swapfactory.SwapFactory,
privkey string,
) backend.Backend {
pk, err := ethcrypto.HexToECDSA(privkey)
require.NoError(t, err)
ec, err := ethclient.Dial(common.DefaultEthEndpoint)
require.NoError(t, err)
t.Cleanup(func() {
ec.Close()
})
cfg := &backend.Config{
Ctx: context.Background(),
@@ -93,7 +114,7 @@ func newBackend(t *testing.T, addr ethcommon.Address, contract *swapfactory.Swap
EthereumPrivateKey: pk,
EthereumClient: ec,
ChainID: big.NewInt(common.GanacheChainID),
MoneroWalletEndpoint: common.DefaultXMRTakerMoneroEndpoint,
MoneroWalletEndpoint: tests.CreateWalletRPCService(t),
MoneroDaemonEndpoint: common.DefaultMoneroDaemonEndpoint,
SwapContract: contract,
SwapContractAddress: addr,
@@ -126,10 +147,11 @@ func TestRecoverer_RecoverFromXMRMakerSecretAndContract_Claim(t *testing.T) {
claimKey := keys.Secp256k1PublicKey.Keccak256()
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)
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)
require.NoError(t, err)
require.True(t, res.Claimed)
@@ -145,10 +167,11 @@ func TestRecoverer_RecoverFromXMRMakerSecretAndContract_Claim_afterTimeout(t *te
claimKey := keys.Secp256k1PublicKey.Keccak256()
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)
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)
require.NoError(t, err)
require.True(t, res.Claimed)
@@ -164,10 +187,11 @@ func TestRecoverer_RecoverFromXMRTakerSecretAndContract_Refund(t *testing.T) {
refundKey := keys.Secp256k1PublicKey.Keccak256()
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)
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)
require.NoError(t, err)
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
if [[ -d "./monero-x86_64-linux-gnu-v0.17.3.2" ]]; then
echo "monero-x86_64-linux-gnu-v0.17.3.2 already installed"
arch=linux64
if [[ -d "monero-bin" ]]; then
echo "$(dirname $(realpath monero-bin)) already installed"
exit 0
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
# 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
# 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..."
./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
echo "starting monero-wallet-rpc on port 18083..."
mkdir 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 &
mkdir -p bob-test-keys
./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=$!
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
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 &
mkdir -p alice-test-keys
./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=$!
# install ganache and run
echo "installing and starting ganache-cli..."
if ! command -v golangci-lint &> /dev/null; then
npm i -g ganache-cli
# install ganache-cli and run
GANACHE_EXEC="$(npm config get prefix)/bin/ganache-cli"
if [[ ! -x "${GANACHE_EXEC}" ]]; then
echo "installing ganache-cli"
npm install --location=global ganache-cli
fi
echo "starting ganache-cli"
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=$!
# wait for servers to start
@@ -35,15 +38,15 @@ sleep 10
echo "starting alice, logs in ./tests/alice.log"
bash scripts/build.sh
./swapd --dev-xmrtaker --libp2p-key=./tests/alice.key &> ./tests/alice.log &
ALICE_PID=$!
ALICE_SWAPD_PID=$!
sleep 3
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 &
BOB_PID=$!
BOB_SWAPD_PID=$!
sleep 3
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 &
CHARLIE_PID=$!
CHARLIE_SWAPD_PID=$!
sleep 3
# run tests
@@ -52,12 +55,12 @@ TESTS=integration go test ./tests -v
OK=$?
# kill processes
kill $MONERO_WALLET_CLI_BOB_PID
kill $MONERO_WALLET_CLI_ALICE_PID
kill $GANACHE_CLI_PID
kill $ALICE_PID
kill $BOB_PID
kill $CHARLIE_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}" || echo "Alice's wallet CLI was not running at end of test"
kill "${GANACHE_CLI_PID}" || echo "ganache-cli was not running at end of test"
kill "${ALICE_SWAPD_PID}" || echo "Alice's swapd was not running at end of test"
kill "${BOB_SWAPD_PID}" || echo "Bob's swapd was not running at end of test"
kill "${CHARLIE_SWAPD_PID}" || echo "Charlie's swapd was not running at end of test"
# rm -rf ./alice-test-keys
# rm -rf ./bob-test-keys
exit $OK
exit $OK

View File

@@ -1,31 +1,20 @@
#!/bin/bash
# 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..."
./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
echo "starting monero-wallet-rpc on port 18083..."
mkdir 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_WALLET_CLI_BOB_PID=$!
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
# install ganache-cli and run
GANACHE_EXEC="$(npm config get prefix)/bin/ganache-cli"
if [[ ! -x "${GANACHE_EXEC}" ]]; then
echo "installing ganache-cli"
npm install --location=global ganache-cli
fi
echo "starting ganache-cli"
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=$!
# wait for servers to start
@@ -37,9 +26,5 @@ go test ./... -v -short -timeout=30m -covermode=atomic -coverprofile=coverage.ou
OK=$?
# kill processes
kill $MONERO_WALLET_CLI_BOB_PID
kill $MONERO_WALLET_CLI_ALICE_PID
kill $GANACHE_CLI_PID
# rm -rf ./alice-test-keys
# rm -rf ./bob-test-keys
exit $OK
kill "${GANACHE_CLI_PID}" || echo "ganache-cli was not running at end of test"
exit $OK

View File

@@ -1,25 +1,25 @@
#!/bin/bash
# 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
LOG_DIR=${TMPDIR:-"/tmp"}
ALICE_P2P_ADDRESS="12D3KooWBD82zGTFqk6Qmu5zeS6dQfiaAcn8go2QWE29HPmRX3yB"
echo "cleanup"
pkill -e -f monero;
pkill -e -f ganache-cli;
killall -v swapd;
pkill -e -f swapcli;
pkill -e -f monero
pkill -e -f ganache-cli
killall -v swapd
pkill -e -f swapcli
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"
cd $MONERO_DIR
cd "${MONERO_DIR}"
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"
sleep 10
@@ -31,19 +31,19 @@ echo "Zzz... 15s"
sleep 15
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"
./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"
../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"
sleep 10
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"
sleep 10

View File

@@ -1,31 +1,34 @@
#!/bin/bash
# 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..."
./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
echo "starting monero-wallet-rpc on port 18083..."
mkdir 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 &
mkdir -p bob-test-keys
./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=$!
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
echo "starting monero-wallet-rpc on port 18084..."
mkdir 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 &
mkdir -p alice-test-keys
./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=$!
# install ganache and run
echo "installing and starting ganache-cli..."
if ! command -v golangci-lint &> /dev/null; then
npm i -g ganache-cli
# install ganache-cli and run
GANACHE_EXEC="$(npm config get prefix)/bin/ganache-cli"
if [[ ! -x "${GANACHE_EXEC}" ]]; then
echo "installing ganache-cli"
npm install --location=global ganache-cli
fi
echo "starting ganache-cli"
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=$!
# wait for servers to start

View File

@@ -2,14 +2,15 @@
bash ./scripts/install-monero-linux.sh
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
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..."
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)
sleep 5

View File

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