From 6e02008f9ea2eb2b55dc583c76b68544cc99e44c Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Thu, 6 Feb 2020 09:40:18 +0100 Subject: [PATCH 01/11] contract, swap: refactor backend to commit on sendTransaction --- contracts/swap/factory.go | 7 ++-- contracts/swap/swap.go | 64 +++-------------------------- swap/cashout.go | 7 ++-- swap/cashout_test.go | 7 ++-- swap/common_test.go | 56 +++++-------------------- swap/simulations_test.go | 3 +- swap/swap.go | 10 +++-- swap/txqueue/backend.go | 86 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 121 insertions(+), 119 deletions(-) create mode 100644 swap/txqueue/backend.go diff --git a/contracts/swap/factory.go b/contracts/swap/factory.go index 5c3c7a0be1..feba4395f5 100644 --- a/contracts/swap/factory.go +++ b/contracts/swap/factory.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" chequebookFactory "github.com/ethersphere/go-sw3/contracts-v0-2-0/simpleswapfactory" + "github.com/ethersphere/swarm/swap/txqueue" ) var ( @@ -26,7 +27,7 @@ var ( type simpleSwapFactory struct { instance *chequebookFactory.SimpleSwapFactory address common.Address - backend Backend + backend txqueue.Backend } // SimpleSwapFactory interface defines the methods available for a factory contract for SimpleSwap @@ -40,7 +41,7 @@ type SimpleSwapFactory interface { } // FactoryAt creates a SimpleSwapFactory instance for the given address and backend -func FactoryAt(address common.Address, backend Backend) (SimpleSwapFactory, error) { +func FactoryAt(address common.Address, backend txqueue.Backend) (SimpleSwapFactory, error) { simple, err := chequebookFactory.NewSimpleSwapFactory(address, backend) if err != nil { return nil, err @@ -83,7 +84,7 @@ func (sf simpleSwapFactory) DeploySimpleSwap(auth *bind.TransactOpts, issuer com return nil, err } - receipt, err := WaitFunc(auth.Context, sf.backend, tx) + receipt, err := txqueue.WaitMined(auth.Context, sf.backend, tx.Hash()) if err != nil { return nil, err } diff --git a/contracts/swap/swap.go b/contracts/swap/swap.go index defbf55d91..14532aa960 100644 --- a/contracts/swap/swap.go +++ b/contracts/swap/swap.go @@ -20,8 +20,6 @@ package swap import ( - "context" - "errors" "fmt" "math/big" @@ -29,21 +27,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" contract "github.com/ethersphere/go-sw3/contracts-v0-2-0/erc20simpleswap" + "github.com/ethersphere/swarm/swap/txqueue" "github.com/ethersphere/swarm/uint256" ) -var ( - // ErrTransactionReverted is given when the transaction that cashes a cheque is reverted - ErrTransactionReverted = errors.New("Transaction reverted") -) - -// Backend wraps all methods required for contract deployment. -type Backend interface { - bind.ContractBackend - TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) - TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) -} - // Contract interface defines the methods exported from the underlying go-bindings for the smart contract type Contract interface { // Withdraw attempts to withdraw ERC20-token from the chequebook @@ -89,13 +76,13 @@ type Params struct { type simpleContract struct { instance *contract.ERC20SimpleSwap address common.Address - backend Backend + backend txqueue.Backend } // InstanceAt creates a new instance of a contract at a specific address. // It assumes that there is an existing contract instance at the given address, or an error is returned // This function is needed to communicate with remote Swap contracts (e.g. sending a cheque) -func InstanceAt(address common.Address, backend Backend) (Contract, error) { +func InstanceAt(address common.Address, backend txqueue.Backend) (Contract, error) { instance, err := contract.NewERC20SimpleSwap(address, backend) if err != nil { return nil, err @@ -110,7 +97,7 @@ func (s simpleContract) Withdraw(auth *bind.TransactOpts, amount *big.Int) (*typ if err != nil { return nil, err } - return WaitFunc(auth.Context, s.backend, tx) + return txqueue.WaitMined(auth.Context, s.backend, tx.Hash()) } // Deposit sends an amount in ERC20 token to the chequebook and blocks until the transaction is mined @@ -140,7 +127,7 @@ func (s simpleContract) Deposit(auth *bind.TransactOpts, amount *big.Int) (*type if err != nil { return nil, err } - return WaitFunc(auth.Context, s.backend, tx) + return txqueue.WaitMined(auth.Context, s.backend, tx.Hash()) } // CashChequeBeneficiaryStart sends the transaction to cash a cheque as the beneficiary @@ -224,44 +211,3 @@ func (s simpleContract) Issuer(opts *bind.CallOpts) (common.Address, error) { func (s simpleContract) PaidOut(opts *bind.CallOpts, addr common.Address) (*big.Int, error) { return s.instance.PaidOut(opts, addr) } - -// WaitFunc is the default function to wait for transactions -// We can overwrite this in tests so that we don't need to wait for mining -var WaitFunc = waitForTx - -// waitForTx waits for transaction to be mined and returns the receipt -func waitForTx(ctx context.Context, backend Backend, tx *types.Transaction) (*types.Receipt, error) { - // it blocks here until tx is mined - receipt, err := bind.WaitMined(ctx, backend, tx) - if err != nil { - return nil, err - } - // indicate whether the transaction did not revert - if receipt.Status != types.ReceiptStatusSuccessful { - return nil, ErrTransactionReverted - } - return receipt, nil -} - -// WaitForTransactionByHash waits for a transaction to by mined by hash -func WaitForTransactionByHash(ctx context.Context, backend Backend, txHash common.Hash) (*types.Receipt, error) { - tx, pending, err := backend.TransactionByHash(ctx, txHash) - if err != nil { - return nil, err - } - - var receipt *types.Receipt - if pending { - receipt, err = WaitFunc(ctx, backend, tx) - if err != nil { - return nil, err - } - } else { - receipt, err = backend.TransactionReceipt(ctx, txHash) - if err != nil { - return nil, err - } - } - - return receipt, nil -} diff --git a/swap/cashout.go b/swap/cashout.go index 1b15383e12..170b8744f0 100644 --- a/swap/cashout.go +++ b/swap/cashout.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/metrics" contract "github.com/ethersphere/swarm/contracts/swap" + "github.com/ethersphere/swarm/swap/txqueue" "github.com/ethersphere/swarm/uint256" ) @@ -31,7 +32,7 @@ const CashChequeBeneficiaryTransactionCost = 50000 // CashoutProcessor holds all relevant fields needed for processing cashouts type CashoutProcessor struct { - backend contract.Backend // ethereum backend to use + backend txqueue.Backend // ethereum backend to use privateKey *ecdsa.PrivateKey // private key to use } @@ -48,7 +49,7 @@ type ActiveCashout struct { } // newCashoutProcessor creates a new instance of CashoutProcessor -func newCashoutProcessor(backend contract.Backend, privateKey *ecdsa.PrivateKey) *CashoutProcessor { +func newCashoutProcessor(backend txqueue.Backend, privateKey *ecdsa.PrivateKey) *CashoutProcessor { return &CashoutProcessor{ backend: backend, privateKey: privateKey, @@ -128,7 +129,7 @@ func (c *CashoutProcessor) waitForAndProcessActiveCashout(activeCashout *ActiveC ctx, cancel := context.WithTimeout(context.Background(), DefaultTransactionTimeout) defer cancel() - receipt, err := contract.WaitForTransactionByHash(ctx, c.backend, activeCashout.TransactionHash) + receipt, err := txqueue.WaitMined(ctx, c.backend, activeCashout.TransactionHash) if err != nil { return err } diff --git a/swap/cashout_test.go b/swap/cashout_test.go index 27bcc46b6b..fc9599904c 100644 --- a/swap/cashout_test.go +++ b/swap/cashout_test.go @@ -22,7 +22,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/log" - contract "github.com/ethersphere/swarm/contracts/swap" + "github.com/ethersphere/swarm/swap/txqueue" "github.com/ethersphere/swarm/uint256" ) @@ -37,7 +37,6 @@ func TestContractIntegration(t *testing.T) { defer reset() payout := uint256.FromUint64(42) - chequebook, err := testDeployWithPrivateKey(context.Background(), backend, ownerKey, ownerAddress, payout) if err != nil { t.Fatal(err) @@ -55,7 +54,7 @@ func TestContractIntegration(t *testing.T) { t.Fatal(err) } - receipt, err := contract.WaitForTransactionByHash(context.Background(), backend, tx.Hash()) + receipt, err := txqueue.WaitMined(nil, backend, tx.Hash()) if err != nil { t.Fatal(err) } @@ -99,7 +98,7 @@ func TestContractIntegration(t *testing.T) { t.Fatal(err) } - receipt, err = contract.WaitForTransactionByHash(context.Background(), backend, tx.Hash()) + receipt, err = txqueue.WaitMined(nil, backend, tx.Hash()) if err != nil { t.Fatal(err) } diff --git a/swap/common_test.go b/swap/common_test.go index 124bbbb7c7..170c2ff802 100644 --- a/swap/common_test.go +++ b/swap/common_test.go @@ -15,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/simulations/adapters" @@ -24,24 +23,20 @@ import ( "github.com/ethersphere/swarm/network" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" + "github.com/ethersphere/swarm/swap/txqueue" "github.com/ethersphere/swarm/uint256" ) // swapTestBackend encapsulates the SimulatedBackend and can offer // additional properties for the tests type swapTestBackend struct { - *backends.SimulatedBackend + *txqueue.TestBackend factoryAddress common.Address // address of the SimpleSwapFactory in the simulated network tokenAddress common.Address // address of the token in the simulated network // the async cashing go routine needs synchronization for tests cashDone chan struct{} } -func (b *swapTestBackend) Close() error { - // Do not close SimulatedBackend as it is a global instance. - return nil -} - var defaultBackend = backends.NewSimulatedBackend(core.GenesisAlloc{ ownerAddress: {Balance: big.NewInt(1000000000000000000)}, beneficiaryAddress: {Balance: big.NewInt(1000000000000000000)}, @@ -50,30 +45,27 @@ var defaultBackend = backends.NewSimulatedBackend(core.GenesisAlloc{ // newTestBackend creates a new test backend instance func newTestBackend(t *testing.T) *swapTestBackend { t.Helper() - // commit the initial "pre-mined" accounts (issuer and beneficiary addresses) - defaultBackend.Commit() + backend := txqueue.NewTestBackend(defaultBackend) // deploy the ERC20-contract // ignore receipt because if there is no error, we can assume everything is fine on a simulated backend - tokenAddress, _, _, err := contractFactory.DeployERC20Mintable(bind.NewKeyedTransactor(ownerKey), defaultBackend) + tokenAddress, _, _, err := contractFactory.DeployERC20Mintable(bind.NewKeyedTransactor(ownerKey), backend) if err != nil { t.Fatal(err) } - defaultBackend.Commit() // deploy a SimpleSwapFactoy // ignore receipt because if there is no error, we can assume everything is fine on a simulated backend // ignore factory instance, because the address is all we need at this point - factoryAddress, _, _, err := contractFactory.DeploySimpleSwapFactory(bind.NewKeyedTransactor(ownerKey), defaultBackend, tokenAddress) + factoryAddress, _, _, err := contractFactory.DeploySimpleSwapFactory(bind.NewKeyedTransactor(ownerKey), backend, tokenAddress) if err != nil { t.Fatal(err) } - defaultBackend.Commit() return &swapTestBackend{ - SimulatedBackend: defaultBackend, - factoryAddress: factoryAddress, - tokenAddress: tokenAddress, + TestBackend: backend, + factoryAddress: factoryAddress, + tokenAddress: tokenAddress, } } @@ -225,46 +217,21 @@ func testCashCheque(s *Swap, cheque *Cheque) { } } -// when testing, we don't need to wait for a transaction to be mined -func testWaitForTx(ctx context.Context, backend cswap.Backend, tx *types.Transaction) (*types.Receipt, error) { - - var stb *swapTestBackend - var ok bool - if stb, ok = backend.(*swapTestBackend); !ok { - return nil, errors.New("not the expected test backend") - } - stb.Commit() - - receipt, err := backend.TransactionReceipt(ctx, tx.Hash()) - if err != nil { - return nil, err - } - if receipt.Status != types.ReceiptStatusSuccessful { - return nil, cswap.ErrTransactionReverted - } - return receipt, nil -} - // setupContractTest is a helper function for setting up the // blockchain wait function for testing func setupContractTest() func() { - // we overwrite the waitForTx function with one which the simulated backend - // immediately commits - currentWaitFunc := cswap.WaitFunc // we also need to store the previous cashCheque function in case this is called multiple times currentCashCheque := defaultCashCheque defaultCashCheque = testCashCheque // overwrite only for the duration of the test, so... - cswap.WaitFunc = testWaitForTx return func() { // ...we need to set it back to original when done - cswap.WaitFunc = currentWaitFunc defaultCashCheque = currentCashCheque } } // deploy for testing (needs simulated backend commit) -func testDeployWithPrivateKey(ctx context.Context, backend cswap.Backend, privateKey *ecdsa.PrivateKey, ownerAddress common.Address, depositAmount *uint256.Uint256) (cswap.Contract, error) { +func testDeployWithPrivateKey(ctx context.Context, backend txqueue.Backend, privateKey *ecdsa.PrivateKey, ownerAddress common.Address, depositAmount *uint256.Uint256) (cswap.Contract, error) { opts := bind.NewKeyedTransactor(privateKey) opts.Context = ctx @@ -286,7 +253,6 @@ func testDeployWithPrivateKey(ctx context.Context, backend cswap.Backend, privat if err != nil { return nil, err } - stb.Commit() // send money into the new chequebook token, err := contractFactory.NewERC20Mintable(stb.tokenAddress, stb) @@ -299,8 +265,8 @@ func testDeployWithPrivateKey(ctx context.Context, backend cswap.Backend, privat if err != nil { return nil, err } - stb.Commit() - receipt, err := stb.TransactionReceipt(ctx, tx.Hash()) + + receipt, err := txqueue.WaitMined(ctx, stb, tx.Hash()) if err != nil { return nil, err } diff --git a/swap/simulations_test.go b/swap/simulations_test.go index 581a2e222e..d481b9c0fd 100644 --- a/swap/simulations_test.go +++ b/swap/simulations_test.go @@ -47,6 +47,7 @@ import ( "github.com/ethersphere/swarm/network/simulation" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" + "github.com/ethersphere/swarm/swap/txqueue" "github.com/ethersphere/swarm/uint256" ) @@ -233,7 +234,7 @@ func newSharedBackendSwaps(t *testing.T, nodeCount int) (*swapSimulationParams, } defaultBackend.Commit() - testBackend := &swapTestBackend{SimulatedBackend: defaultBackend, factoryAddress: factoryAddress, tokenAddress: tokenAddress} + testBackend := &swapTestBackend{TestBackend: txqueue.NewTestBackend(defaultBackend), factoryAddress: factoryAddress, tokenAddress: tokenAddress} // finally, create all Swap instances for each node, which share the same backend var owner *Owner defParams := newDefaultParams(t) diff --git a/swap/swap.go b/swap/swap.go index bd2d5c8dd9..b6fce71b9b 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -39,6 +39,7 @@ import ( "github.com/ethersphere/swarm/network" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" + "github.com/ethersphere/swarm/swap/txqueue" "github.com/ethersphere/swarm/uint256" ) @@ -60,7 +61,7 @@ type Swap struct { peers map[enode.ID]*Peer // map of all swap Peers peersLock sync.RWMutex // lock for peers map owner *Owner // contract access - backend contract.Backend // the backend (blockchain) used + backend txqueue.Backend // the backend (blockchain) used chainID uint64 // id of the chain the backend is connected to params *Params // economic and operational parameters contract contract.Contract // reference to the smart contract @@ -135,7 +136,7 @@ func swapRotatingFileHandler(logdir string) (log.Handler, error) { } // newSwapInstance is a swap constructor function without integrity checks -func newSwapInstance(stateStore state.Store, owner *Owner, backend contract.Backend, chainID uint64, params *Params, chequebookFactory contract.SimpleSwapFactory) *Swap { +func newSwapInstance(stateStore state.Store, owner *Owner, backend txqueue.Backend, chainID uint64, params *Params, chequebookFactory contract.SimpleSwapFactory) *Swap { return &Swap{ store: stateStore, peers: make(map[enode.ID]*Peer), @@ -193,6 +194,7 @@ func New(dbPath string, prvkey *ecdsa.PrivateKey, backendURL string, params *Par // create the owner of SWAP owner := createOwner(prvkey) + // initialize the factory factory, err := createFactory(factoryAddress, chainID, backend) if err != nil { @@ -246,7 +248,7 @@ const ( ) // createFactory determines the factory address and returns and error if no factory address has been specified or is unknown for the network -func createFactory(factoryAddress common.Address, chainID *big.Int, backend contract.Backend) (factory swap.SimpleSwapFactory, err error) { +func createFactory(factoryAddress common.Address, chainID *big.Int, backend txqueue.Backend) (factory swap.SimpleSwapFactory, err error) { if (factoryAddress == common.Address{}) { if factoryAddress, err = contract.FactoryAddressForNetwork(chainID.Uint64()); err != nil { return nil, err @@ -497,7 +499,7 @@ func cashCheque(s *Swap, cheque *Cheque) { if err != nil { metrics.GetOrRegisterCounter("swap.cheques.cashed.errors", nil).Inc(1) - swapLog.Error("cashing cheque:", err) + swapLog.Error("cashing cheque:", "error", err) } } diff --git a/swap/txqueue/backend.go b/swap/txqueue/backend.go new file mode 100644 index 0000000000..12531a7525 --- /dev/null +++ b/swap/txqueue/backend.go @@ -0,0 +1,86 @@ +package txqueue + +import ( + "context" + "errors" + "time" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +var ( + // ErrTransactionReverted is given when the transaction that cashes a cheque is reverted + ErrTransactionReverted = errors.New("Transaction reverted") +) + +// Backend is the minimum amount of functionality required by the underlying ethereum backend +type Backend interface { + bind.ContractBackend + TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) +} + +// TestBackend is the backend to use for tests with a simulated backend +type TestBackend struct { + *backends.SimulatedBackend +} + +// WaitMined waits until either the transaction with the given hash has been mined or the context is cancelled +func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt, error) { + queryTicker := time.NewTicker(time.Second) + defer queryTicker.Stop() + + if ctx == nil { + ctx = context.Background() + } + + for { + receipt, err := b.TransactionReceipt(ctx, hash) + if receipt != nil { + // indicate whether the transaction did not revert + if receipt.Status != types.ReceiptStatusSuccessful { + return nil, ErrTransactionReverted + } + return receipt, nil + } + if err != nil { + log.Trace("Receipt retrieval failed", "err", err) + } else { + log.Trace("Transaction not yet mined") + } + // Wait for the next round. + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-queryTicker.C: + } + } +} + +// SendTransaction adds a commit after a successful send +func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction) (err error) { + err = b.SimulatedBackend.SendTransaction(ctx, tx) + if err == nil { + b.SimulatedBackend.Commit() + } + return err +} + +// Close overrides Close so a SimulatedBackend can be used accross multiple tests for now +func (b *TestBackend) Close() { + +} + +// NewTestBackend returns a new TestBackend for the given SimulatedBackend +// It also causes an initial commit to make sure that genesis accounts are set up +func NewTestBackend(backend *backends.SimulatedBackend) *TestBackend { + backend.Commit() + return &TestBackend{ + SimulatedBackend: backend, + } +} From 7c29ae8e8f7eb466b6119ed609820bc2ec1794c6 Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Fri, 7 Feb 2020 14:30:31 +0100 Subject: [PATCH 02/11] swap/txqueue: make comment for Close function clearer --- swap/txqueue/backend.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/swap/txqueue/backend.go b/swap/txqueue/backend.go index 12531a7525..d18a0c8435 100644 --- a/swap/txqueue/backend.go +++ b/swap/txqueue/backend.go @@ -71,7 +71,9 @@ func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction return err } -// Close overrides Close so a SimulatedBackend can be used accross multiple tests for now +// Close overrides the Close function of the underlying SimulatedBackend so that it does nothing +// This allows the same SimulatedBackend backend to be reused accross tests +// This is necessary due to some memory leakage issues with the used version of the SimulatedBackend func (b *TestBackend) Close() { } From e2d821d5736380e2a3b22231dadb380e4e094424 Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Mon, 10 Feb 2020 12:31:32 +0100 Subject: [PATCH 03/11] swap: rename swap/txqueue package to swap/chain --- contracts/swap/factory.go | 8 ++-- contracts/swap/swap.go | 10 ++--- swap/cashout.go | 8 ++-- swap/cashout_test.go | 6 +-- swap/common_test.go | 10 ++--- swap/simulations_test.go | 4 +- swap/swap.go | 8 ++-- swap/txqueue/backend.go | 88 --------------------------------------- 8 files changed, 27 insertions(+), 115 deletions(-) delete mode 100644 swap/txqueue/backend.go diff --git a/contracts/swap/factory.go b/contracts/swap/factory.go index feba4395f5..38f399d96a 100644 --- a/contracts/swap/factory.go +++ b/contracts/swap/factory.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" chequebookFactory "github.com/ethersphere/go-sw3/contracts-v0-2-0/simpleswapfactory" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" ) var ( @@ -27,7 +27,7 @@ var ( type simpleSwapFactory struct { instance *chequebookFactory.SimpleSwapFactory address common.Address - backend txqueue.Backend + backend chain.Backend } // SimpleSwapFactory interface defines the methods available for a factory contract for SimpleSwap @@ -41,7 +41,7 @@ type SimpleSwapFactory interface { } // FactoryAt creates a SimpleSwapFactory instance for the given address and backend -func FactoryAt(address common.Address, backend txqueue.Backend) (SimpleSwapFactory, error) { +func FactoryAt(address common.Address, backend chain.Backend) (SimpleSwapFactory, error) { simple, err := chequebookFactory.NewSimpleSwapFactory(address, backend) if err != nil { return nil, err @@ -84,7 +84,7 @@ func (sf simpleSwapFactory) DeploySimpleSwap(auth *bind.TransactOpts, issuer com return nil, err } - receipt, err := txqueue.WaitMined(auth.Context, sf.backend, tx.Hash()) + receipt, err := chain.WaitMined(auth.Context, sf.backend, tx.Hash()) if err != nil { return nil, err } diff --git a/contracts/swap/swap.go b/contracts/swap/swap.go index 14532aa960..28af227267 100644 --- a/contracts/swap/swap.go +++ b/contracts/swap/swap.go @@ -27,7 +27,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" contract "github.com/ethersphere/go-sw3/contracts-v0-2-0/erc20simpleswap" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" "github.com/ethersphere/swarm/uint256" ) @@ -76,13 +76,13 @@ type Params struct { type simpleContract struct { instance *contract.ERC20SimpleSwap address common.Address - backend txqueue.Backend + backend chain.Backend } // InstanceAt creates a new instance of a contract at a specific address. // It assumes that there is an existing contract instance at the given address, or an error is returned // This function is needed to communicate with remote Swap contracts (e.g. sending a cheque) -func InstanceAt(address common.Address, backend txqueue.Backend) (Contract, error) { +func InstanceAt(address common.Address, backend chain.Backend) (Contract, error) { instance, err := contract.NewERC20SimpleSwap(address, backend) if err != nil { return nil, err @@ -97,7 +97,7 @@ func (s simpleContract) Withdraw(auth *bind.TransactOpts, amount *big.Int) (*typ if err != nil { return nil, err } - return txqueue.WaitMined(auth.Context, s.backend, tx.Hash()) + return chain.WaitMined(auth.Context, s.backend, tx.Hash()) } // Deposit sends an amount in ERC20 token to the chequebook and blocks until the transaction is mined @@ -127,7 +127,7 @@ func (s simpleContract) Deposit(auth *bind.TransactOpts, amount *big.Int) (*type if err != nil { return nil, err } - return txqueue.WaitMined(auth.Context, s.backend, tx.Hash()) + return chain.WaitMined(auth.Context, s.backend, tx.Hash()) } // CashChequeBeneficiaryStart sends the transaction to cash a cheque as the beneficiary diff --git a/swap/cashout.go b/swap/cashout.go index 170b8744f0..9d62250c64 100644 --- a/swap/cashout.go +++ b/swap/cashout.go @@ -23,7 +23,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/metrics" contract "github.com/ethersphere/swarm/contracts/swap" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" "github.com/ethersphere/swarm/uint256" ) @@ -32,7 +32,7 @@ const CashChequeBeneficiaryTransactionCost = 50000 // CashoutProcessor holds all relevant fields needed for processing cashouts type CashoutProcessor struct { - backend txqueue.Backend // ethereum backend to use + backend chain.Backend // ethereum backend to use privateKey *ecdsa.PrivateKey // private key to use } @@ -49,7 +49,7 @@ type ActiveCashout struct { } // newCashoutProcessor creates a new instance of CashoutProcessor -func newCashoutProcessor(backend txqueue.Backend, privateKey *ecdsa.PrivateKey) *CashoutProcessor { +func newCashoutProcessor(backend chain.Backend, privateKey *ecdsa.PrivateKey) *CashoutProcessor { return &CashoutProcessor{ backend: backend, privateKey: privateKey, @@ -129,7 +129,7 @@ func (c *CashoutProcessor) waitForAndProcessActiveCashout(activeCashout *ActiveC ctx, cancel := context.WithTimeout(context.Background(), DefaultTransactionTimeout) defer cancel() - receipt, err := txqueue.WaitMined(ctx, c.backend, activeCashout.TransactionHash) + receipt, err := chain.WaitMined(ctx, c.backend, activeCashout.TransactionHash) if err != nil { return err } diff --git a/swap/cashout_test.go b/swap/cashout_test.go index fc9599904c..18d56da4ce 100644 --- a/swap/cashout_test.go +++ b/swap/cashout_test.go @@ -22,7 +22,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/log" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" "github.com/ethersphere/swarm/uint256" ) @@ -54,7 +54,7 @@ func TestContractIntegration(t *testing.T) { t.Fatal(err) } - receipt, err := txqueue.WaitMined(nil, backend, tx.Hash()) + receipt, err := chain.WaitMined(nil, backend, tx.Hash()) if err != nil { t.Fatal(err) } @@ -98,7 +98,7 @@ func TestContractIntegration(t *testing.T) { t.Fatal(err) } - receipt, err = txqueue.WaitMined(nil, backend, tx.Hash()) + receipt, err = chain.WaitMined(nil, backend, tx.Hash()) if err != nil { t.Fatal(err) } diff --git a/swap/common_test.go b/swap/common_test.go index 170c2ff802..c3acef8bec 100644 --- a/swap/common_test.go +++ b/swap/common_test.go @@ -23,14 +23,14 @@ import ( "github.com/ethersphere/swarm/network" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" "github.com/ethersphere/swarm/uint256" ) // swapTestBackend encapsulates the SimulatedBackend and can offer // additional properties for the tests type swapTestBackend struct { - *txqueue.TestBackend + *chain.TestBackend factoryAddress common.Address // address of the SimpleSwapFactory in the simulated network tokenAddress common.Address // address of the token in the simulated network // the async cashing go routine needs synchronization for tests @@ -46,7 +46,7 @@ var defaultBackend = backends.NewSimulatedBackend(core.GenesisAlloc{ func newTestBackend(t *testing.T) *swapTestBackend { t.Helper() - backend := txqueue.NewTestBackend(defaultBackend) + backend := chain.NewTestBackend(defaultBackend) // deploy the ERC20-contract // ignore receipt because if there is no error, we can assume everything is fine on a simulated backend tokenAddress, _, _, err := contractFactory.DeployERC20Mintable(bind.NewKeyedTransactor(ownerKey), backend) @@ -231,7 +231,7 @@ func setupContractTest() func() { } // deploy for testing (needs simulated backend commit) -func testDeployWithPrivateKey(ctx context.Context, backend txqueue.Backend, privateKey *ecdsa.PrivateKey, ownerAddress common.Address, depositAmount *uint256.Uint256) (cswap.Contract, error) { +func testDeployWithPrivateKey(ctx context.Context, backend chain.Backend, privateKey *ecdsa.PrivateKey, ownerAddress common.Address, depositAmount *uint256.Uint256) (cswap.Contract, error) { opts := bind.NewKeyedTransactor(privateKey) opts.Context = ctx @@ -266,7 +266,7 @@ func testDeployWithPrivateKey(ctx context.Context, backend txqueue.Backend, priv return nil, err } - receipt, err := txqueue.WaitMined(ctx, stb, tx.Hash()) + receipt, err := chain.WaitMined(ctx, stb, tx.Hash()) if err != nil { return nil, err } diff --git a/swap/simulations_test.go b/swap/simulations_test.go index d481b9c0fd..c30bedbe4c 100644 --- a/swap/simulations_test.go +++ b/swap/simulations_test.go @@ -47,7 +47,7 @@ import ( "github.com/ethersphere/swarm/network/simulation" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" "github.com/ethersphere/swarm/uint256" ) @@ -234,7 +234,7 @@ func newSharedBackendSwaps(t *testing.T, nodeCount int) (*swapSimulationParams, } defaultBackend.Commit() - testBackend := &swapTestBackend{TestBackend: txqueue.NewTestBackend(defaultBackend), factoryAddress: factoryAddress, tokenAddress: tokenAddress} + testBackend := &swapTestBackend{TestBackend: chain.NewTestBackend(defaultBackend), factoryAddress: factoryAddress, tokenAddress: tokenAddress} // finally, create all Swap instances for each node, which share the same backend var owner *Owner defParams := newDefaultParams(t) diff --git a/swap/swap.go b/swap/swap.go index b6fce71b9b..0db9fdff3e 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -39,7 +39,7 @@ import ( "github.com/ethersphere/swarm/network" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" - "github.com/ethersphere/swarm/swap/txqueue" + "github.com/ethersphere/swarm/swap/chain" "github.com/ethersphere/swarm/uint256" ) @@ -61,7 +61,7 @@ type Swap struct { peers map[enode.ID]*Peer // map of all swap Peers peersLock sync.RWMutex // lock for peers map owner *Owner // contract access - backend txqueue.Backend // the backend (blockchain) used + backend chain.Backend // the backend (blockchain) used chainID uint64 // id of the chain the backend is connected to params *Params // economic and operational parameters contract contract.Contract // reference to the smart contract @@ -136,7 +136,7 @@ func swapRotatingFileHandler(logdir string) (log.Handler, error) { } // newSwapInstance is a swap constructor function without integrity checks -func newSwapInstance(stateStore state.Store, owner *Owner, backend txqueue.Backend, chainID uint64, params *Params, chequebookFactory contract.SimpleSwapFactory) *Swap { +func newSwapInstance(stateStore state.Store, owner *Owner, backend chain.Backend, chainID uint64, params *Params, chequebookFactory contract.SimpleSwapFactory) *Swap { return &Swap{ store: stateStore, peers: make(map[enode.ID]*Peer), @@ -248,7 +248,7 @@ const ( ) // createFactory determines the factory address and returns and error if no factory address has been specified or is unknown for the network -func createFactory(factoryAddress common.Address, chainID *big.Int, backend txqueue.Backend) (factory swap.SimpleSwapFactory, err error) { +func createFactory(factoryAddress common.Address, chainID *big.Int, backend chain.Backend) (factory swap.SimpleSwapFactory, err error) { if (factoryAddress == common.Address{}) { if factoryAddress, err = contract.FactoryAddressForNetwork(chainID.Uint64()); err != nil { return nil, err diff --git a/swap/txqueue/backend.go b/swap/txqueue/backend.go deleted file mode 100644 index d18a0c8435..0000000000 --- a/swap/txqueue/backend.go +++ /dev/null @@ -1,88 +0,0 @@ -package txqueue - -import ( - "context" - "errors" - "time" - - "github.com/ethereum/go-ethereum/log" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" -) - -var ( - // ErrTransactionReverted is given when the transaction that cashes a cheque is reverted - ErrTransactionReverted = errors.New("Transaction reverted") -) - -// Backend is the minimum amount of functionality required by the underlying ethereum backend -type Backend interface { - bind.ContractBackend - TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) - TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) -} - -// TestBackend is the backend to use for tests with a simulated backend -type TestBackend struct { - *backends.SimulatedBackend -} - -// WaitMined waits until either the transaction with the given hash has been mined or the context is cancelled -func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt, error) { - queryTicker := time.NewTicker(time.Second) - defer queryTicker.Stop() - - if ctx == nil { - ctx = context.Background() - } - - for { - receipt, err := b.TransactionReceipt(ctx, hash) - if receipt != nil { - // indicate whether the transaction did not revert - if receipt.Status != types.ReceiptStatusSuccessful { - return nil, ErrTransactionReverted - } - return receipt, nil - } - if err != nil { - log.Trace("Receipt retrieval failed", "err", err) - } else { - log.Trace("Transaction not yet mined") - } - // Wait for the next round. - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-queryTicker.C: - } - } -} - -// SendTransaction adds a commit after a successful send -func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction) (err error) { - err = b.SimulatedBackend.SendTransaction(ctx, tx) - if err == nil { - b.SimulatedBackend.Commit() - } - return err -} - -// Close overrides the Close function of the underlying SimulatedBackend so that it does nothing -// This allows the same SimulatedBackend backend to be reused accross tests -// This is necessary due to some memory leakage issues with the used version of the SimulatedBackend -func (b *TestBackend) Close() { - -} - -// NewTestBackend returns a new TestBackend for the given SimulatedBackend -// It also causes an initial commit to make sure that genesis accounts are set up -func NewTestBackend(backend *backends.SimulatedBackend) *TestBackend { - backend.Commit() - return &TestBackend{ - SimulatedBackend: backend, - } -} From 68876805fae5776a3463a0a663dcbc3dc8b6445c Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Mon, 10 Feb 2020 14:27:03 +0100 Subject: [PATCH 04/11] swap/chain: readd missing file --- swap/chain/backend.go | 78 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 swap/chain/backend.go diff --git a/swap/chain/backend.go b/swap/chain/backend.go new file mode 100644 index 0000000000..2f37347a06 --- /dev/null +++ b/swap/chain/backend.go @@ -0,0 +1,78 @@ +package chain + +import ( + "context" + "time" + + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// Backend is the minimum amount of functionality required by the underlying ethereum backend +type Backend interface { + bind.ContractBackend + TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) + TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) +} + +// TestBackend is the backend to use for tests with a simulated backend +type TestBackend struct { + *backends.SimulatedBackend +} + +// WaitMined waits until either the transaction with the given hash has been mined or the context is cancelled +func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt, error) { + queryTicker := time.NewTicker(time.Second) + defer queryTicker.Stop() + + if ctx == nil { + ctx = context.Background() + } + + for { + receipt, err := b.TransactionReceipt(ctx, hash) + if receipt != nil { + return receipt, nil + } + if err != nil { + log.Trace("Receipt retrieval failed", "err", err) + } else { + log.Trace("Transaction not yet mined") + } + // Wait for the next round. + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-queryTicker.C: + } + } +} + +// SendTransaction adds a commit after a successful send +func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction) (err error) { + err = b.SimulatedBackend.SendTransaction(ctx, tx) + if err == nil { + b.SimulatedBackend.Commit() + } + return err +} + +// Close overrides the Close function of the underlying SimulatedBackend so that it does nothing +// This allows the same SimulatedBackend backend to be reused accross tests +// This is necessary due to some memory leakage issues with the used version of the SimulatedBackend +func (b *TestBackend) Close() { + +} + +// NewTestBackend returns a new TestBackend for the given SimulatedBackend +// It also causes an initial commit to make sure that genesis accounts are set up +func NewTestBackend(backend *backends.SimulatedBackend) *TestBackend { + backend.Commit() + return &TestBackend{ + SimulatedBackend: backend, + } +} From 2dc3e8b86b89a501568c04790a28ff6c7d827ce7 Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Mon, 10 Feb 2020 14:35:08 +0100 Subject: [PATCH 05/11] swap/chain: fix spelling mistake --- swap/chain/backend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/chain/backend.go b/swap/chain/backend.go index 2f37347a06..b91611ff89 100644 --- a/swap/chain/backend.go +++ b/swap/chain/backend.go @@ -62,7 +62,7 @@ func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction } // Close overrides the Close function of the underlying SimulatedBackend so that it does nothing -// This allows the same SimulatedBackend backend to be reused accross tests +// This allows the same SimulatedBackend backend to be reused across tests // This is necessary due to some memory leakage issues with the used version of the SimulatedBackend func (b *TestBackend) Close() { From 7e67c082b1ccccb2ad38bf091c1bbac00a9f3dd4 Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Tue, 11 Feb 2020 10:38:51 +0100 Subject: [PATCH 06/11] swap: restoree lost ErrTransactionReverted functionality --- swap/chain/backend.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/swap/chain/backend.go b/swap/chain/backend.go index b91611ff89..ab260f571d 100644 --- a/swap/chain/backend.go +++ b/swap/chain/backend.go @@ -2,6 +2,7 @@ package chain import ( "context" + "errors" "time" "github.com/ethereum/go-ethereum/log" @@ -12,6 +13,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +var ( + // ErrTransactionReverted is given when the transaction that cashes a cheque is reverted + ErrTransactionReverted = errors.New("Transaction reverted") +) + // Backend is the minimum amount of functionality required by the underlying ethereum backend type Backend interface { bind.ContractBackend @@ -36,6 +42,9 @@ func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt for { receipt, err := b.TransactionReceipt(ctx, hash) if receipt != nil { + if receipt.Status != types.ReceiptStatusSuccessful { + return nil, ErrTransactionReverted + } return receipt, nil } if err != nil { From d3ff20b0f3f9bc836765c4e1f453907e041fc98b Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Tue, 11 Feb 2020 10:41:10 +0100 Subject: [PATCH 07/11] swap/chain: check err first in WaitMined --- swap/chain/backend.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/swap/chain/backend.go b/swap/chain/backend.go index ab260f571d..a34867aaeb 100644 --- a/swap/chain/backend.go +++ b/swap/chain/backend.go @@ -35,23 +35,19 @@ func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt queryTicker := time.NewTicker(time.Second) defer queryTicker.Stop() - if ctx == nil { - ctx = context.Background() - } - for { receipt, err := b.TransactionReceipt(ctx, hash) + if err != nil { + log.Trace("Receipt retrieval failed", "err", err) + } if receipt != nil { if receipt.Status != types.ReceiptStatusSuccessful { return nil, ErrTransactionReverted } return receipt, nil } - if err != nil { - log.Trace("Receipt retrieval failed", "err", err) - } else { - log.Trace("Transaction not yet mined") - } + + log.Trace("Transaction not yet mined") // Wait for the next round. select { case <-ctx.Done(): From 5ab4da1e46e3d6cfd32432981ecdc89b661230b2 Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Tue, 11 Feb 2020 11:01:54 +0100 Subject: [PATCH 08/11] swap/chain: add comment about WaitMined's origin --- swap/chain/backend.go | 1 + 1 file changed, 1 insertion(+) diff --git a/swap/chain/backend.go b/swap/chain/backend.go index a34867aaeb..9466244077 100644 --- a/swap/chain/backend.go +++ b/swap/chain/backend.go @@ -31,6 +31,7 @@ type TestBackend struct { } // WaitMined waits until either the transaction with the given hash has been mined or the context is cancelled +// this is an adapted version of go-ethereums bind.WaitMined func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt, error) { queryTicker := time.NewTicker(time.Second) defer queryTicker.Stop() From 8e58360e3d666c6084da8752930a38f42458f398 Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Tue, 11 Feb 2020 14:52:37 +0100 Subject: [PATCH 09/11] swap, swap/chain: move testbackend to mock package --- swap/chain/backend.go | 31 --------------------------- swap/chain/mock/testbackend.go | 38 ++++++++++++++++++++++++++++++++++ swap/common_test.go | 5 +++-- swap/simulations_test.go | 4 ++-- 4 files changed, 43 insertions(+), 35 deletions(-) create mode 100644 swap/chain/mock/testbackend.go diff --git a/swap/chain/backend.go b/swap/chain/backend.go index 9466244077..18837f34bc 100644 --- a/swap/chain/backend.go +++ b/swap/chain/backend.go @@ -8,7 +8,6 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" ) @@ -25,11 +24,6 @@ type Backend interface { TransactionByHash(ctx context.Context, txHash common.Hash) (*types.Transaction, bool, error) } -// TestBackend is the backend to use for tests with a simulated backend -type TestBackend struct { - *backends.SimulatedBackend -} - // WaitMined waits until either the transaction with the given hash has been mined or the context is cancelled // this is an adapted version of go-ethereums bind.WaitMined func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt, error) { @@ -57,28 +51,3 @@ func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt } } } - -// SendTransaction adds a commit after a successful send -func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction) (err error) { - err = b.SimulatedBackend.SendTransaction(ctx, tx) - if err == nil { - b.SimulatedBackend.Commit() - } - return err -} - -// Close overrides the Close function of the underlying SimulatedBackend so that it does nothing -// This allows the same SimulatedBackend backend to be reused across tests -// This is necessary due to some memory leakage issues with the used version of the SimulatedBackend -func (b *TestBackend) Close() { - -} - -// NewTestBackend returns a new TestBackend for the given SimulatedBackend -// It also causes an initial commit to make sure that genesis accounts are set up -func NewTestBackend(backend *backends.SimulatedBackend) *TestBackend { - backend.Commit() - return &TestBackend{ - SimulatedBackend: backend, - } -} diff --git a/swap/chain/mock/testbackend.go b/swap/chain/mock/testbackend.go new file mode 100644 index 0000000000..3d888c2f31 --- /dev/null +++ b/swap/chain/mock/testbackend.go @@ -0,0 +1,38 @@ +package testing + +import ( + "context" + + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/core/types" +) + +// TestBackend is the backend to use for tests with a simulated backend +type TestBackend struct { + *backends.SimulatedBackend +} + +// SendTransaction adds a commit after a successful send +func (b *TestBackend) SendTransaction(ctx context.Context, tx *types.Transaction) (err error) { + err = b.SimulatedBackend.SendTransaction(ctx, tx) + if err == nil { + b.SimulatedBackend.Commit() + } + return err +} + +// Close overrides the Close function of the underlying SimulatedBackend so that it does nothing +// This allows the same SimulatedBackend backend to be reused across tests +// This is necessary due to some memory leakage issues with the used version of the SimulatedBackend +func (b *TestBackend) Close() { + +} + +// NewTestBackend returns a new TestBackend for the given SimulatedBackend +// It also causes an initial commit to make sure that genesis accounts are set up +func NewTestBackend(backend *backends.SimulatedBackend) *TestBackend { + backend.Commit() + return &TestBackend{ + SimulatedBackend: backend, + } +} diff --git a/swap/common_test.go b/swap/common_test.go index c3acef8bec..9fb2ca6343 100644 --- a/swap/common_test.go +++ b/swap/common_test.go @@ -24,13 +24,14 @@ import ( "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" "github.com/ethersphere/swarm/swap/chain" + mock "github.com/ethersphere/swarm/swap/chain/mock" "github.com/ethersphere/swarm/uint256" ) // swapTestBackend encapsulates the SimulatedBackend and can offer // additional properties for the tests type swapTestBackend struct { - *chain.TestBackend + *mock.TestBackend factoryAddress common.Address // address of the SimpleSwapFactory in the simulated network tokenAddress common.Address // address of the token in the simulated network // the async cashing go routine needs synchronization for tests @@ -46,7 +47,7 @@ var defaultBackend = backends.NewSimulatedBackend(core.GenesisAlloc{ func newTestBackend(t *testing.T) *swapTestBackend { t.Helper() - backend := chain.NewTestBackend(defaultBackend) + backend := mock.NewTestBackend(defaultBackend) // deploy the ERC20-contract // ignore receipt because if there is no error, we can assume everything is fine on a simulated backend tokenAddress, _, _, err := contractFactory.DeployERC20Mintable(bind.NewKeyedTransactor(ownerKey), backend) diff --git a/swap/simulations_test.go b/swap/simulations_test.go index c30bedbe4c..a73911d08d 100644 --- a/swap/simulations_test.go +++ b/swap/simulations_test.go @@ -47,7 +47,7 @@ import ( "github.com/ethersphere/swarm/network/simulation" "github.com/ethersphere/swarm/p2p/protocols" "github.com/ethersphere/swarm/state" - "github.com/ethersphere/swarm/swap/chain" + mock "github.com/ethersphere/swarm/swap/chain/mock" "github.com/ethersphere/swarm/uint256" ) @@ -234,7 +234,7 @@ func newSharedBackendSwaps(t *testing.T, nodeCount int) (*swapSimulationParams, } defaultBackend.Commit() - testBackend := &swapTestBackend{TestBackend: chain.NewTestBackend(defaultBackend), factoryAddress: factoryAddress, tokenAddress: tokenAddress} + testBackend := &swapTestBackend{TestBackend: mock.NewTestBackend(defaultBackend), factoryAddress: factoryAddress, tokenAddress: tokenAddress} // finally, create all Swap instances for each node, which share the same backend var owner *Owner defParams := newDefaultParams(t) From 234b7d702e4a0d3153812578df792f85a700604b Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Tue, 11 Feb 2020 16:17:44 +0100 Subject: [PATCH 10/11] swap: fix package name --- swap/chain/mock/testbackend.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/chain/mock/testbackend.go b/swap/chain/mock/testbackend.go index 3d888c2f31..40b64c4b46 100644 --- a/swap/chain/mock/testbackend.go +++ b/swap/chain/mock/testbackend.go @@ -1,4 +1,4 @@ -package testing +package mock import ( "context" From bf003f249f6dbd4a3c4914d21cd2509fc373644d Mon Sep 17 00:00:00 2001 From: Ralph Pichler Date: Wed, 12 Feb 2020 10:49:00 +0100 Subject: [PATCH 11/11] swap: remove ticker, make logs lower case --- swap/chain/backend.go | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/swap/chain/backend.go b/swap/chain/backend.go index 18837f34bc..54ad6b55b1 100644 --- a/swap/chain/backend.go +++ b/swap/chain/backend.go @@ -27,13 +27,10 @@ type Backend interface { // WaitMined waits until either the transaction with the given hash has been mined or the context is cancelled // this is an adapted version of go-ethereums bind.WaitMined func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt, error) { - queryTicker := time.NewTicker(time.Second) - defer queryTicker.Stop() - for { receipt, err := b.TransactionReceipt(ctx, hash) if err != nil { - log.Trace("Receipt retrieval failed", "err", err) + log.Error("receipt retrieval failed", "err", err) } if receipt != nil { if receipt.Status != types.ReceiptStatusSuccessful { @@ -42,12 +39,12 @@ func WaitMined(ctx context.Context, b Backend, hash common.Hash) (*types.Receipt return receipt, nil } - log.Trace("Transaction not yet mined") + log.Trace("transaction not yet mined", "tx", hash) // Wait for the next round. select { case <-ctx.Done(): return nil, ctx.Err() - case <-queryTicker.C: + case <-time.After(1 * time.Second): } } }