From 205090344ab41db328d3fe28c7880299742822d0 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 3 Sep 2019 13:11:56 +0200 Subject: [PATCH 01/39] swap: move oracle, paymentThreshold and disconnectThreshold to peer --- swap/peer.go | 22 +++++++++----- swap/protocol_test.go | 4 +-- swap/swap.go | 61 ++++++++++++++++++------------------- swap/swap_test.go | 70 +++++++++++++++++++++---------------------- 4 files changed, 80 insertions(+), 77 deletions(-) diff --git a/swap/peer.go b/swap/peer.go index 92b02e91fe..a880193dea 100644 --- a/swap/peer.go +++ b/swap/peer.go @@ -30,18 +30,24 @@ var ErrDontOwe = errors.New("no negative balance") // Peer is a devp2p peer for the Swap protocol type Peer struct { *protocols.Peer - swap *Swap - beneficiary common.Address - contractAddress common.Address - lastReceivedCheque *Cheque + swap *Swap + beneficiary common.Address + contractAddress common.Address + lastReceivedCheque *Cheque + oracle HoneyOracle // the oracle providing the ether price for honey + paymentThreshold int64 // balance difference required for sending cheque + disconnectThreshold int64 // balance difference required for dropping peer } // NewPeer creates a new swap Peer instance func NewPeer(p *protocols.Peer, s *Swap, beneficiary common.Address, contractAddress common.Address) *Peer { return &Peer{ - Peer: p, - swap: s, - beneficiary: beneficiary, - contractAddress: contractAddress, + Peer: p, + swap: s, + beneficiary: beneficiary, + contractAddress: contractAddress, + paymentThreshold: DefaultPaymentThreshold, + disconnectThreshold: DefaultDisconnectThreshold, + oracle: NewPriceOracle(), } } diff --git a/swap/protocol_test.go b/swap/protocol_test.go index 07da1a2f34..76baa99d44 100644 --- a/swap/protocol_test.go +++ b/swap/protocol_test.go @@ -207,7 +207,7 @@ func TestTriggerPaymentThreshold(t *testing.T) { defer cleanup() // create a dummy pper - cPeer := newDummyPeerWithSpec(Spec) + cPeer := newDummyPeer(Spec) creditor := NewPeer(cPeer.Peer, debitorSwap, common.Address{}, common.Address{}) // set the creditor as peer into the debitor's swap debitorSwap.peers[creditor.ID()] = creditor @@ -262,7 +262,7 @@ func TestTriggerDisconnectThreshold(t *testing.T) { defer clean() // create a dummy pper - cPeer := newDummyPeerWithSpec(Spec) + cPeer := newDummyPeer(Spec) debitor := NewPeer(cPeer.Peer, creditorSwap, common.Address{}, common.Address{}) // set the debitor as peer into the creditor's swap creditorSwap.peers[debitor.ID()] = debitor diff --git a/swap/swap.go b/swap/swap.go index a4ee6435c2..eea2a4d2d5 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -47,22 +47,19 @@ var ErrInvalidChequeSignature = errors.New("invalid cheque signature") // A node maintains an individual balance with every peer // Only messages which have a price will be accounted for type Swap struct { - api API - store state.Store // store is needed in order to keep balances and cheques across sessions - accountingLock sync.RWMutex // lock for data consistency in accounting-related functions - balances map[enode.ID]int64 // map of balances for each peer - balancesLock sync.RWMutex // lock for balances map - cheques map[enode.ID]*Cheque // map of cheques for each peer - chequesLock sync.RWMutex // lock for cheques map - peers map[enode.ID]*Peer // map of all swap Peers - peersLock sync.RWMutex // lock for peers map - backend contract.Backend // the backend (blockchain) used - owner *Owner // contract access - params *Params // economic and operational parameters - contract swap.Contract // reference to the smart contract - oracle PriceOracle // the oracle providing the ether price for honey - paymentThreshold int64 // balance difference required for sending cheque - disconnectThreshold int64 // balance difference required for dropping peer + api API + store state.Store // store is needed in order to keep balances and cheques across sessions + accountingLock sync.RWMutex // lock for data consistency in accounting-related functions + balances map[enode.ID]int64 // map of balances for each peer + balancesLock sync.RWMutex // lock for balances map + cheques map[enode.ID]*Cheque // map of cheques for each peer + chequesLock sync.RWMutex // lock for cheques map + peers map[enode.ID]*Peer // map of all swap Peers + peersLock sync.RWMutex // lock for peers map + backend contract.Backend // the backend (blockchain) used + owner *Owner // contract access + params *Params // economic and operational parameters + contract swap.Contract // reference to the smart contract } // Owner encapsulates information related to accessing the contract @@ -88,16 +85,13 @@ func NewParams() *Params { // New - swap constructor func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Address, backend contract.Backend) *Swap { return &Swap{ - store: stateStore, - balances: make(map[enode.ID]int64), - cheques: make(map[enode.ID]*Cheque), - peers: make(map[enode.ID]*Peer), - backend: backend, - owner: createOwner(prvkey, contract), - params: NewParams(), - paymentThreshold: DefaultPaymentThreshold, - disconnectThreshold: DefaultDisconnectThreshold, - oracle: NewPriceOracle(), + store: stateStore, + balances: make(map[enode.ID]int64), + cheques: make(map[enode.ID]*Cheque), + peers: make(map[enode.ID]*Peer), + backend: backend, + owner: createOwner(prvkey, contract), + params: NewParams(), } } @@ -158,8 +152,9 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { if !exists { return fmt.Errorf("peer %v does not exist", peer.ID()) } - if balance >= s.disconnectThreshold { - return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), s.disconnectThreshold) + disconnectThreshold := s.peers[peer.ID()].disconnectThreshold + if balance >= disconnectThreshold { + return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) } var newBalance int64 @@ -171,8 +166,10 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - if newBalance <= -s.paymentThreshold { - log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", s.paymentThreshold) + paymentThreshold := s.peers[peer.ID()].paymentThreshold + + if newBalance <= -paymentThreshold { + log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) swapPeer, ok := s.getPeer(peer.ID()) if !ok { return fmt.Errorf("peer %s not found", peer) @@ -289,7 +286,7 @@ func (s *Swap) processAndVerifyCheque(cheque *Cheque, p *Peer) (uint64, error) { lastCheque := s.loadLastReceivedCheque(p) // TODO: there should probably be a lock here? - expectedAmount, err := s.oracle.GetPrice(cheque.Honey) + expectedAmount, err := p.oracle.GetPrice(cheque.Honey) if err != nil { return 0, err } @@ -390,7 +387,7 @@ func (s *Swap) createCheque(swapPeer *Peer) (*Cheque, error) { honey := uint64(-peerBalance) var amount uint64 - amount, err = s.oracle.GetPrice(honey) + amount, err = swapPeer.oracle.GetPrice(honey) if err != nil { return nil, fmt.Errorf("error getting price from oracle: %s", err.Error()) } diff --git a/swap/swap_test.go b/swap/swap_test.go index a2092f5a7a..5780151690 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -107,9 +107,9 @@ func TestPeerBalance(t *testing.T) { defer clean() // test for correct value - testPeer := newDummyPeer() - swap.balances[testPeer.ID()] = 888 - b, err := swap.Balance(testPeer.ID()) + testPeer := newDummyPeer(Spec) + swap.balances[testPeer.Peer.ID()] = 888 + b, err := swap.Balance(testPeer.Peer.ID()) if err != nil { t.Fatal(err) } @@ -139,18 +139,18 @@ func TestAllBalances(t *testing.T) { } // test balance addition for peer - testPeer := newDummyPeer() - swap.balances[testPeer.ID()] = 808 - testBalances(t, swap, map[enode.ID]int64{testPeer.ID(): 808}) + testPeer := newDummyPeer(Spec) + swap.balances[testPeer.Peer.ID()] = 808 + testBalances(t, swap, map[enode.ID]int64{testPeer.Peer.ID(): 808}) // test successive balance addition for peer - testPeer2 := newDummyPeer() - swap.balances[testPeer2.ID()] = 909 - testBalances(t, swap, map[enode.ID]int64{testPeer.ID(): 808, testPeer2.ID(): 909}) + testPeer2 := newDummyPeer(Spec) + swap.balances[testPeer2.Peer.ID()] = 909 + testBalances(t, swap, map[enode.ID]int64{testPeer.Peer.ID(): 808, testPeer2.Peer.ID(): 909}) // test balance change for peer - swap.balances[testPeer.ID()] = 303 - testBalances(t, swap, map[enode.ID]int64{testPeer.ID(): 303, testPeer2.ID(): 909}) + swap.balances[testPeer.Peer.ID()] = 303 + testBalances(t, swap, map[enode.ID]int64{testPeer.Peer.ID(): 303, testPeer2.Peer.ID(): 909}) } func testBalances(t *testing.T, swap *Swap, expectedBalances map[enode.ID]int64) { @@ -268,13 +268,15 @@ func TestRepeatedBookings(t *testing.T) { var bookings []booking // credits to peer 1 - testPeer := newDummyPeer() + testPeer := newDummyPeer(Spec) + swap.peers[testPeer.Peer.ID()] = testPeer bookingAmount := int64(mrand.Intn(100)) bookingQuantity := 1 + mrand.Intn(10) testPeerBookings(t, swap, &bookings, bookingAmount, bookingQuantity, testPeer.Peer) // debits to peer 2 - testPeer2 := newDummyPeer() + testPeer2 := newDummyPeer(Spec) + swap.peers[testPeer2.Peer.ID()] = testPeer2 bookingAmount = 0 - int64(mrand.Intn(100)) bookingQuantity = 1 + mrand.Intn(10) testPeerBookings(t, swap, &bookings, bookingAmount, bookingQuantity, testPeer2.Peer) @@ -319,8 +321,8 @@ func TestResetBalance(t *testing.T) { // create Peer instances // NOTE: remember that these are peer instances representing each **a model of the remote peer** for every local node // so creditor is the model of the remote mode for the debitor! (and vice versa) - cPeer := newDummyPeerWithSpec(Spec) - dPeer := newDummyPeerWithSpec(Spec) + cPeer := newDummyPeer(Spec) + dPeer := newDummyPeer(Spec) creditor := NewPeer(cPeer.Peer, debitorSwap, creditorSwap.owner.address, debitorSwap.owner.Contract) debitor := NewPeer(dPeer.Peer, creditorSwap, debitorSwap.owner.address, debitorSwap.owner.Contract) @@ -429,7 +431,7 @@ func calculateExpectedBalances(swap *Swap, bookings []booking) map[enode.ID]int6 peerID := booking.peer.ID() peerBalance := expectedBalances[peerID] // balance is not expected to be affected once past the disconnect threshold - if peerBalance < swap.disconnectThreshold { + if peerBalance < swap.peers[peerID].disconnectThreshold { peerBalance += booking.amount } expectedBalances[peerID] = peerBalance @@ -448,11 +450,11 @@ func TestRestoreBalanceFromStateStore(t *testing.T) { swap, testDir := newBaseTestSwap(t, ownerKey) defer os.RemoveAll(testDir) - testPeer := newDummyPeer() - swap.balances[testPeer.ID()] = -8888 + testPeer := newDummyPeer(Spec) + swap.balances[testPeer.Peer.ID()] = -8888 - tmpBalance := swap.balances[testPeer.ID()] - swap.store.Put(testPeer.ID().String(), &tmpBalance) + tmpBalance := swap.balances[testPeer.Peer.ID()] + swap.store.Put(testPeer.Peer.ID().String(), &tmpBalance) err := swap.store.Close() if err != nil { @@ -467,7 +469,7 @@ func TestRestoreBalanceFromStateStore(t *testing.T) { } var newBalance int64 - stateStore.Get(testPeer.ID().String(), &newBalance) + stateStore.Get(testPeer.Peer.ID().String(), &newBalance) // compare the balances if tmpBalance != newBalance { @@ -519,24 +521,22 @@ func newTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, func()) { return swap, clean } -type dummyPeer struct { - *protocols.Peer -} - -// creates a dummy protocols.Peer with dummy MsgReadWriter -func newDummyPeer() *dummyPeer { - return newDummyPeerWithSpec(nil) +// creates a dummy swap.Peer +func newDummyPeer(spec *protocols.Spec) *Peer { + return &Peer{ + Peer: newDummyProtocolPeer(spec), + paymentThreshold: DefaultPaymentThreshold, + disconnectThreshold: DefaultDisconnectThreshold, + oracle: NewPriceOracle(), + } } // creates a dummy protocols.Peer with dummy MsgReadWriter -func newDummyPeerWithSpec(spec *protocols.Spec) *dummyPeer { +func newDummyProtocolPeer(spec *protocols.Spec) *protocols.Peer { id := adapters.RandomNodeConfig().ID rw := &dummyMsgRW{} protoPeer := protocols.NewPeer(p2p.NewPeer(id, "testPeer", nil), rw, spec) - dummy := &dummyPeer{ - Peer: protoPeer, - } - return dummy + return protoPeer } // creates cheque structure for testing @@ -837,7 +837,7 @@ func TestSaveAndLoadLastReceivedCheque(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() - testPeer := NewPeer(newDummyPeer().Peer, swap, common.Address{}, common.Address{}) + testPeer := NewPeer(newDummyProtocolPeer(Spec), swap, common.Address{}, common.Address{}) testCheque := newTestCheque() if err := swap.saveLastReceivedCheque(testPeer, testCheque); err != nil { @@ -862,7 +862,7 @@ func newTestSwapAndPeer(t *testing.T, key *ecdsa.PrivateKey) (*Swap, *Peer, func swap, clean := newTestSwap(t, key) // owner address is the beneficiary (counterparty) for the peer // that's because we expect cheques we receive to be signed by the address we would issue cheques to - peer := NewPeer(newDummyPeer().Peer, swap, ownerAddress, testChequeContract) + peer := NewPeer(newDummyProtocolPeer(Spec), swap, ownerAddress, testChequeContract) // we need to adjust the owner address on swap because we will issue cheques to beneficiaryAddress swap.owner.address = beneficiaryAddress return swap, peer, clean From 83b9c3f1b47a3e093d2341a42f02ad3051e1a943 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 3 Sep 2019 13:13:36 +0200 Subject: [PATCH 02/39] made thresholdOracle --- swap/{oracle.go => honeyOracle.go} | 4 +-- swap/tresholdOracle.go | 40 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) rename swap/{oracle.go => honeyOracle.go} (95%) create mode 100644 swap/tresholdOracle.go diff --git a/swap/oracle.go b/swap/honeyOracle.go similarity index 95% rename from swap/oracle.go rename to swap/honeyOracle.go index d907ddf473..64f7a3fd8f 100644 --- a/swap/oracle.go +++ b/swap/honeyOracle.go @@ -17,13 +17,13 @@ package swap // PriceOracle is the interface through which Oracles will deliver prices -type PriceOracle interface { +type HoneyOracle interface { GetPrice(honey uint64) (uint64, error) } // NewPriceOracle returns the actual oracle to be used for discovering the price // It will return a default one -func NewPriceOracle() PriceOracle { +func NewPriceOracle() HoneyOracle { return &fixedPriceOracle{ honeyPrice: defaultHoneyPrice, } diff --git a/swap/tresholdOracle.go b/swap/tresholdOracle.go new file mode 100644 index 0000000000..80ab689f52 --- /dev/null +++ b/swap/tresholdOracle.go @@ -0,0 +1,40 @@ +// Copyright 2019 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package swap + +// TresholdOralce is the interface through which Oracles will deliver payment thresholds +type TresholdOralce interface { + GetPaymentThreshold() (int, error) +} + +// NewThresholdOracle returns the actual oracle to be used for discovering the threshold +// It will return a default one +func NewThresholdOracle() TresholdOralce { + return &fixedPaymentThreshold{ + paymentThreshold: DefaultPaymentThreshold, + } +} + +// FixedPaymentThreshold is a paymentThreshold oracle which which returns a fixed price +type fixedPaymentThreshold struct { + paymentThreshold int +} + +// GetPrice returns the actual price for honey +func (fpo *fixedPaymentThreshold) GetPaymentThreshold() (int, error) { + return fpo.paymentThreshold, nil +} From 82b100e450df65b160ae28d80d306df093a03c97 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 3 Sep 2019 13:27:44 +0200 Subject: [PATCH 03/39] swap: using the paymentThresholdOracle, renaming priceOracle to honeyOracle --- swap/honeyOracle.go | 6 +++--- swap/peer.go | 28 ++++++++++++++-------------- swap/swap.go | 6 +++--- swap/swap_test.go | 8 ++++---- swap/tresholdOracle.go | 12 ++++++------ 5 files changed, 30 insertions(+), 30 deletions(-) diff --git a/swap/honeyOracle.go b/swap/honeyOracle.go index 64f7a3fd8f..8526945ac4 100644 --- a/swap/honeyOracle.go +++ b/swap/honeyOracle.go @@ -16,14 +16,14 @@ package swap -// PriceOracle is the interface through which Oracles will deliver prices +// HoneyOracle is the interface through which Oracles will deliver prices type HoneyOracle interface { GetPrice(honey uint64) (uint64, error) } -// NewPriceOracle returns the actual oracle to be used for discovering the price +// NewHoneyPriceOracle returns the actual oracle to be used for discovering the price // It will return a default one -func NewPriceOracle() HoneyOracle { +func NewHoneyPriceOracle() HoneyOracle { return &fixedPriceOracle{ honeyPrice: defaultHoneyPrice, } diff --git a/swap/peer.go b/swap/peer.go index a880193dea..020e8f41ee 100644 --- a/swap/peer.go +++ b/swap/peer.go @@ -30,24 +30,24 @@ var ErrDontOwe = errors.New("no negative balance") // Peer is a devp2p peer for the Swap protocol type Peer struct { *protocols.Peer - swap *Swap - beneficiary common.Address - contractAddress common.Address - lastReceivedCheque *Cheque - oracle HoneyOracle // the oracle providing the ether price for honey - paymentThreshold int64 // balance difference required for sending cheque - disconnectThreshold int64 // balance difference required for dropping peer + swap *Swap + beneficiary common.Address + contractAddress common.Address + lastReceivedCheque *Cheque + honeyOracle HoneyOracle // the oracle providing the ether price for honey + paymentThresholdOracle ThresholdOracle // the oracle providing the payment treshold + disconnectThreshold int64 // balance difference required for dropping peer } // NewPeer creates a new swap Peer instance func NewPeer(p *protocols.Peer, s *Swap, beneficiary common.Address, contractAddress common.Address) *Peer { return &Peer{ - Peer: p, - swap: s, - beneficiary: beneficiary, - contractAddress: contractAddress, - paymentThreshold: DefaultPaymentThreshold, - disconnectThreshold: DefaultDisconnectThreshold, - oracle: NewPriceOracle(), + Peer: p, + swap: s, + beneficiary: beneficiary, + contractAddress: contractAddress, + paymentThresholdOracle: NewThresholdOracle(), + disconnectThreshold: DefaultDisconnectThreshold, + honeyOracle: NewHoneyPriceOracle(), } } diff --git a/swap/swap.go b/swap/swap.go index eea2a4d2d5..8dc438865e 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -166,7 +166,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - paymentThreshold := s.peers[peer.ID()].paymentThreshold + paymentThreshold, _ := s.peers[peer.ID()].paymentThresholdOracle.GetPaymentThreshold() if newBalance <= -paymentThreshold { log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) @@ -286,7 +286,7 @@ func (s *Swap) processAndVerifyCheque(cheque *Cheque, p *Peer) (uint64, error) { lastCheque := s.loadLastReceivedCheque(p) // TODO: there should probably be a lock here? - expectedAmount, err := p.oracle.GetPrice(cheque.Honey) + expectedAmount, err := p.honeyOracle.GetPrice(cheque.Honey) if err != nil { return 0, err } @@ -387,7 +387,7 @@ func (s *Swap) createCheque(swapPeer *Peer) (*Cheque, error) { honey := uint64(-peerBalance) var amount uint64 - amount, err = swapPeer.oracle.GetPrice(honey) + amount, err = swapPeer.honeyOracle.GetPrice(honey) if err != nil { return nil, fmt.Errorf("error getting price from oracle: %s", err.Error()) } diff --git a/swap/swap_test.go b/swap/swap_test.go index 5780151690..bd9e14f9c0 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -524,10 +524,10 @@ func newTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, func()) { // creates a dummy swap.Peer func newDummyPeer(spec *protocols.Spec) *Peer { return &Peer{ - Peer: newDummyProtocolPeer(spec), - paymentThreshold: DefaultPaymentThreshold, - disconnectThreshold: DefaultDisconnectThreshold, - oracle: NewPriceOracle(), + Peer: newDummyProtocolPeer(spec), + paymentThresholdOracle: NewThresholdOracle(), + disconnectThreshold: DefaultDisconnectThreshold, + honeyOracle: NewHoneyPriceOracle(), } } diff --git a/swap/tresholdOracle.go b/swap/tresholdOracle.go index 80ab689f52..6ba08cd436 100644 --- a/swap/tresholdOracle.go +++ b/swap/tresholdOracle.go @@ -16,14 +16,14 @@ package swap -// TresholdOralce is the interface through which Oracles will deliver payment thresholds -type TresholdOralce interface { - GetPaymentThreshold() (int, error) +// ThresholdOracle is the interface through which Oracles will deliver payment thresholds +type ThresholdOracle interface { + GetPaymentThreshold() (int64, error) } // NewThresholdOracle returns the actual oracle to be used for discovering the threshold // It will return a default one -func NewThresholdOracle() TresholdOralce { +func NewThresholdOracle() ThresholdOracle { return &fixedPaymentThreshold{ paymentThreshold: DefaultPaymentThreshold, } @@ -31,10 +31,10 @@ func NewThresholdOracle() TresholdOralce { // FixedPaymentThreshold is a paymentThreshold oracle which which returns a fixed price type fixedPaymentThreshold struct { - paymentThreshold int + paymentThreshold int64 } // GetPrice returns the actual price for honey -func (fpo *fixedPaymentThreshold) GetPaymentThreshold() (int, error) { +func (fpo *fixedPaymentThreshold) GetPaymentThreshold() (int64, error) { return fpo.paymentThreshold, nil } From 6adc5541cf47c8966be1f72b31535b6da75b3f06 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 3 Sep 2019 14:45:27 +0200 Subject: [PATCH 04/39] swap, api, cmd, swarm: made payment and disconnect threshold modifiable --- api/config.go | 43 +++++++------- cmd/swarm/config.go | 56 ++++++++++--------- cmd/swarm/flags.go | 10 ++++ swap/honeyOracle.go | 1 + swap/peer.go | 5 +- swap/swap.go | 48 +++++++++------- swap/swap_test.go | 4 +- .../{tresholdOracle.go => thresholdOracle.go} | 4 +- swarm.go | 9 ++- 9 files changed, 106 insertions(+), 74 deletions(-) rename swap/{tresholdOracle.go => thresholdOracle.go} (94%) diff --git a/api/config.go b/api/config.go index b587611611..6b81d1be40 100644 --- a/api/config.go +++ b/api/config.go @@ -32,6 +32,7 @@ import ( "github.com/ethersphere/swarm/network" "github.com/ethersphere/swarm/pss" "github.com/ethersphere/swarm/storage" + "github.com/ethersphere/swarm/swap" ) const ( @@ -52,8 +53,10 @@ type Config struct { BaseKey []byte // Swap configs - SwapBackendURL string - SwapEnabled bool + SwapBackendURL string + SwapEnabled bool + SwapPaymentThreshold int64 + SwapDisconnectThreshold int64 *network.HiveParams Pss *pss.Params @@ -81,26 +84,28 @@ type Config struct { privateKey *ecdsa.PrivateKey } -//create a default config with all parameters to set to defaults +//NewConfig creates a default config with all parameters to set to defaults func NewConfig() (c *Config) { c = &Config{ - FileStoreParams: storage.NewFileStoreParams(), - HiveParams: network.NewHiveParams(), - Pss: pss.NewParams(), - ListenAddr: DefaultHTTPListenAddr, - Port: DefaultHTTPPort, - Path: node.DefaultDataDir(), - EnsAPIs: nil, - EnsRoot: ens.TestNetAddress, - NetworkID: network.DefaultNetworkID, - SyncEnabled: true, - SyncingSkipCheck: false, - MaxStreamPeerServers: 10000, - DeliverySkipCheck: true, - SyncUpdateDelay: 15 * time.Second, - SwapEnabled: false, - SwapBackendURL: "", + FileStoreParams: storage.NewFileStoreParams(), + HiveParams: network.NewHiveParams(), + Pss: pss.NewParams(), + ListenAddr: DefaultHTTPListenAddr, + Port: DefaultHTTPPort, + Path: node.DefaultDataDir(), + EnsAPIs: nil, + EnsRoot: ens.TestNetAddress, + NetworkID: network.DefaultNetworkID, + SyncEnabled: true, + SyncingSkipCheck: false, + MaxStreamPeerServers: 10000, + DeliverySkipCheck: true, + SyncUpdateDelay: 15 * time.Second, + SwapEnabled: false, + SwapBackendURL: "", + SwapPaymentThreshold: swap.DefaultPaymentThreshold, + SwapDisconnectThreshold: swap.DefaultDisconnectThreshold, } return diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index c0a35a777a..993e772dde 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -59,33 +59,35 @@ var ( //constants for environment variables const ( - SwarmEnvChequebookAddr = "SWARM_CHEQUEBOOK_ADDR" - SwarmEnvAccount = "SWARM_ACCOUNT" - SwarmEnvBzzKeyHex = "SWARM_BZZ_KEY_HEX" - SwarmEnvListenAddr = "SWARM_LISTEN_ADDR" - SwarmEnvPort = "SWARM_PORT" - SwarmEnvNetworkID = "SWARM_NETWORK_ID" - SwarmEnvSwapEnable = "SWARM_SWAP_ENABLE" - SwarmEnvSwapBackendURL = "SWARM_SWAP_BACKEND_URL" - SwarmEnvSyncDisable = "SWARM_SYNC_DISABLE" - SwarmEnvSyncUpdateDelay = "SWARM_ENV_SYNC_UPDATE_DELAY" - SwarmEnvMaxStreamPeerServers = "SWARM_ENV_MAX_STREAM_PEER_SERVERS" - SwarmEnvLightNodeEnable = "SWARM_LIGHT_NODE_ENABLE" - SwarmEnvDeliverySkipCheck = "SWARM_DELIVERY_SKIP_CHECK" - SwarmEnvENSAPI = "SWARM_ENS_API" - SwarmEnvENSAddr = "SWARM_ENS_ADDR" - SwarmEnvCORS = "SWARM_CORS" - SwarmEnvBootnodes = "SWARM_BOOTNODES" - SwarmEnvPSSEnable = "SWARM_PSS_ENABLE" - SwarmEnvStorePath = "SWARM_STORE_PATH" - SwarmEnvStoreCapacity = "SWARM_STORE_CAPACITY" - SwarmEnvStoreCacheCapacity = "SWARM_STORE_CACHE_CAPACITY" - SwarmEnvBootnodeMode = "SWARM_BOOTNODE_MODE" - SwarmEnvNATInterface = "SWARM_NAT_INTERFACE" - SwarmAccessPassword = "SWARM_ACCESS_PASSWORD" - SwarmAutoDefaultPath = "SWARM_AUTO_DEFAULTPATH" - SwarmGlobalstoreAPI = "SWARM_GLOBALSTORE_API" - GethEnvDataDir = "GETH_DATADIR" + SwarmEnvChequebookAddr = "SWARM_CHEQUEBOOK_ADDR" + SwarmEnvAccount = "SWARM_ACCOUNT" + SwarmEnvBzzKeyHex = "SWARM_BZZ_KEY_HEX" + SwarmEnvListenAddr = "SWARM_LISTEN_ADDR" + SwarmEnvPort = "SWARM_PORT" + SwarmEnvNetworkID = "SWARM_NETWORK_ID" + SwarmEnvSwapEnable = "SWARM_SWAP_ENABLE" + SwarmEnvSwapBackendURL = "SWARM_SWAP_BACKEND_URL" + SwarmEnvSwapPaymentThreshold = "SWARM_SWAP_PAYMENT_THRESHOLD" + SwarmEnvSwapDisconnectThreshold = "SWARM_SWAP_DISCONNECT_THRESHOLD" + SwarmEnvSyncDisable = "SWARM_SYNC_DISABLE" + SwarmEnvSyncUpdateDelay = "SWARM_ENV_SYNC_UPDATE_DELAY" + SwarmEnvMaxStreamPeerServers = "SWARM_ENV_MAX_STREAM_PEER_SERVERS" + SwarmEnvLightNodeEnable = "SWARM_LIGHT_NODE_ENABLE" + SwarmEnvDeliverySkipCheck = "SWARM_DELIVERY_SKIP_CHECK" + SwarmEnvENSAPI = "SWARM_ENS_API" + SwarmEnvENSAddr = "SWARM_ENS_ADDR" + SwarmEnvCORS = "SWARM_CORS" + SwarmEnvBootnodes = "SWARM_BOOTNODES" + SwarmEnvPSSEnable = "SWARM_PSS_ENABLE" + SwarmEnvStorePath = "SWARM_STORE_PATH" + SwarmEnvStoreCapacity = "SWARM_STORE_CAPACITY" + SwarmEnvStoreCacheCapacity = "SWARM_STORE_CACHE_CAPACITY" + SwarmEnvBootnodeMode = "SWARM_BOOTNODE_MODE" + SwarmEnvNATInterface = "SWARM_NAT_INTERFACE" + SwarmAccessPassword = "SWARM_ACCESS_PASSWORD" + SwarmAutoDefaultPath = "SWARM_AUTO_DEFAULTPATH" + SwarmGlobalstoreAPI = "SWARM_GLOBALSTORE_API" + GethEnvDataDir = "GETH_DATADIR" ) // These settings ensure that TOML keys use the same names as Go struct fields. diff --git a/cmd/swarm/flags.go b/cmd/swarm/flags.go index 0b62888553..13f64d7fae 100644 --- a/cmd/swarm/flags.go +++ b/cmd/swarm/flags.go @@ -65,6 +65,16 @@ var ( Usage: "URL of the Ethereum API provider to use to settle SWAP payments", EnvVar: SwarmEnvSwapBackendURL, } + SwarmEnvSwapPaymentThresholdFlag = cli.Int64Flag{ + Name: "swap-payment-threshold", + Usage: "honey amount indebted to a peer at which you will initiate payment", + EnvVar: SwarmEnvSwapPaymentThreshold, + } + SwarmEnvDisconnectThresholdFlag = cli.Int64Flag{ + Name: "swap-disconnect-threshold", + Usage: "honey amount at debt of a peer at which you will disconnect", + EnvVar: SwarmEnvSwapDisconnectThreshold, + } SwarmSyncDisabledFlag = cli.BoolTFlag{ Name: "nosync", Usage: "Disable swarm syncing", diff --git a/swap/honeyOracle.go b/swap/honeyOracle.go index 8526945ac4..50ae044936 100644 --- a/swap/honeyOracle.go +++ b/swap/honeyOracle.go @@ -24,6 +24,7 @@ type HoneyOracle interface { // NewHoneyPriceOracle returns the actual oracle to be used for discovering the price // It will return a default one func NewHoneyPriceOracle() HoneyOracle { + return &fixedPriceOracle{ honeyPrice: defaultHoneyPrice, } diff --git a/swap/peer.go b/swap/peer.go index 020e8f41ee..0cd0f75b2e 100644 --- a/swap/peer.go +++ b/swap/peer.go @@ -41,13 +41,14 @@ type Peer struct { // NewPeer creates a new swap Peer instance func NewPeer(p *protocols.Peer, s *Swap, beneficiary common.Address, contractAddress common.Address) *Peer { + paymentThreshold, _ := s.defaultThresholdOracle.GetPaymentThreshold() return &Peer{ Peer: p, swap: s, beneficiary: beneficiary, contractAddress: contractAddress, - paymentThresholdOracle: NewThresholdOracle(), - disconnectThreshold: DefaultDisconnectThreshold, + paymentThresholdOracle: NewThresholdOracle(paymentThreshold), + disconnectThreshold: s.defaultDisconnectThreshold, honeyOracle: NewHoneyPriceOracle(), } } diff --git a/swap/swap.go b/swap/swap.go index 8dc438865e..03d5e29cd2 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -47,19 +47,22 @@ var ErrInvalidChequeSignature = errors.New("invalid cheque signature") // A node maintains an individual balance with every peer // Only messages which have a price will be accounted for type Swap struct { - api API - store state.Store // store is needed in order to keep balances and cheques across sessions - accountingLock sync.RWMutex // lock for data consistency in accounting-related functions - balances map[enode.ID]int64 // map of balances for each peer - balancesLock sync.RWMutex // lock for balances map - cheques map[enode.ID]*Cheque // map of cheques for each peer - chequesLock sync.RWMutex // lock for cheques map - peers map[enode.ID]*Peer // map of all swap Peers - peersLock sync.RWMutex // lock for peers map - backend contract.Backend // the backend (blockchain) used - owner *Owner // contract access - params *Params // economic and operational parameters - contract swap.Contract // reference to the smart contract + api API + store state.Store // store is needed in order to keep balances and cheques across sessions + accountingLock sync.RWMutex // lock for data consistency in accounting-related functions + balances map[enode.ID]int64 // map of balances for each peer + balancesLock sync.RWMutex // lock for balances map + cheques map[enode.ID]*Cheque // map of cheques for each peer + chequesLock sync.RWMutex // lock for cheques map + peers map[enode.ID]*Peer // map of all swap Peers + peersLock sync.RWMutex // lock for peers map + backend contract.Backend // the backend (blockchain) used + owner *Owner // contract access + params *Params // economic and operational parameters + contract swap.Contract // reference to the smart contract + defaultDisconnectThreshold int64 + defaultThresholdOracle ThresholdOracle + defaultHoneyPriceOracle HoneyOracle } // Owner encapsulates information related to accessing the contract @@ -83,15 +86,18 @@ func NewParams() *Params { } // New - swap constructor -func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Address, backend contract.Backend) *Swap { +func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Address, backend contract.Backend, disconnectThreshold int64, paymentThreshold int64) *Swap { return &Swap{ - store: stateStore, - balances: make(map[enode.ID]int64), - cheques: make(map[enode.ID]*Cheque), - peers: make(map[enode.ID]*Peer), - backend: backend, - owner: createOwner(prvkey, contract), - params: NewParams(), + store: stateStore, + balances: make(map[enode.ID]int64), + cheques: make(map[enode.ID]*Cheque), + peers: make(map[enode.ID]*Peer), + backend: backend, + owner: createOwner(prvkey, contract), + params: NewParams(), + defaultDisconnectThreshold: disconnectThreshold, + defaultThresholdOracle: NewThresholdOracle(paymentThreshold), + defaultHoneyPriceOracle: NewHoneyPriceOracle(), } } diff --git a/swap/swap_test.go b/swap/swap_test.go index bd9e14f9c0..5dd28bc5af 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -504,7 +504,7 @@ func newBaseTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, string) { } log.Debug("creating simulated backend") - swap := New(stateStore, key, common.Address{}, testBackend) + swap := New(stateStore, key, common.Address{}, testBackend, DefaultDisconnectThreshold, DefaultPaymentThreshold) return swap, dir } @@ -525,7 +525,7 @@ func newTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, func()) { func newDummyPeer(spec *protocols.Spec) *Peer { return &Peer{ Peer: newDummyProtocolPeer(spec), - paymentThresholdOracle: NewThresholdOracle(), + paymentThresholdOracle: NewThresholdOracle(DefaultPaymentThreshold), disconnectThreshold: DefaultDisconnectThreshold, honeyOracle: NewHoneyPriceOracle(), } diff --git a/swap/tresholdOracle.go b/swap/thresholdOracle.go similarity index 94% rename from swap/tresholdOracle.go rename to swap/thresholdOracle.go index 6ba08cd436..1cfbd3a1f9 100644 --- a/swap/tresholdOracle.go +++ b/swap/thresholdOracle.go @@ -23,9 +23,9 @@ type ThresholdOracle interface { // NewThresholdOracle returns the actual oracle to be used for discovering the threshold // It will return a default one -func NewThresholdOracle() ThresholdOracle { +func NewThresholdOracle(price int64) ThresholdOracle { return &fixedPaymentThreshold{ - paymentThreshold: DefaultPaymentThreshold, + paymentThreshold: price, } } diff --git a/swarm.go b/swarm.go index 7a9e2a04b7..37c3751b1e 100644 --- a/swarm.go +++ b/swarm.go @@ -133,7 +133,14 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e return nil, err } // create the accounting objects - self.swap = swap.New(swapStore, self.privateKey, self.config.Contract, self.backend) + self.swap = swap.New( + swapStore, + self.privateKey, + self.config.Contract, + self.backend, + self.config.SwapDisconnectThreshold, + self.config.SwapPaymentThreshold, + ) // start anonymous metrics collection self.accountingMetrics = protocols.SetupAccountingMetrics(10*time.Second, filepath.Join(config.Path, "metrics.db")) } From 578a2fc18cae57ef8f003956201939ffe3697c88 Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 5 Sep 2019 11:34:36 +0200 Subject: [PATCH 05/39] swap: redo refactor => disconnectthreshold, thresholdOracle, honeyPriceOracle from peer to swap --- swap/peer.go | 23 +++++++------------- swap/swap.go | 60 ++++++++++++++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 45 deletions(-) diff --git a/swap/peer.go b/swap/peer.go index 0cd0f75b2e..92b02e91fe 100644 --- a/swap/peer.go +++ b/swap/peer.go @@ -30,25 +30,18 @@ var ErrDontOwe = errors.New("no negative balance") // Peer is a devp2p peer for the Swap protocol type Peer struct { *protocols.Peer - swap *Swap - beneficiary common.Address - contractAddress common.Address - lastReceivedCheque *Cheque - honeyOracle HoneyOracle // the oracle providing the ether price for honey - paymentThresholdOracle ThresholdOracle // the oracle providing the payment treshold - disconnectThreshold int64 // balance difference required for dropping peer + swap *Swap + beneficiary common.Address + contractAddress common.Address + lastReceivedCheque *Cheque } // NewPeer creates a new swap Peer instance func NewPeer(p *protocols.Peer, s *Swap, beneficiary common.Address, contractAddress common.Address) *Peer { - paymentThreshold, _ := s.defaultThresholdOracle.GetPaymentThreshold() return &Peer{ - Peer: p, - swap: s, - beneficiary: beneficiary, - contractAddress: contractAddress, - paymentThresholdOracle: NewThresholdOracle(paymentThreshold), - disconnectThreshold: s.defaultDisconnectThreshold, - honeyOracle: NewHoneyPriceOracle(), + Peer: p, + swap: s, + beneficiary: beneficiary, + contractAddress: contractAddress, } } diff --git a/swap/swap.go b/swap/swap.go index 03d5e29cd2..6ca0c17bdf 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -47,22 +47,22 @@ var ErrInvalidChequeSignature = errors.New("invalid cheque signature") // A node maintains an individual balance with every peer // Only messages which have a price will be accounted for type Swap struct { - api API - store state.Store // store is needed in order to keep balances and cheques across sessions - accountingLock sync.RWMutex // lock for data consistency in accounting-related functions - balances map[enode.ID]int64 // map of balances for each peer - balancesLock sync.RWMutex // lock for balances map - cheques map[enode.ID]*Cheque // map of cheques for each peer - chequesLock sync.RWMutex // lock for cheques map - peers map[enode.ID]*Peer // map of all swap Peers - peersLock sync.RWMutex // lock for peers map - backend contract.Backend // the backend (blockchain) used - owner *Owner // contract access - params *Params // economic and operational parameters - contract swap.Contract // reference to the smart contract - defaultDisconnectThreshold int64 - defaultThresholdOracle ThresholdOracle - defaultHoneyPriceOracle HoneyOracle + api API + store state.Store // store is needed in order to keep balances and cheques across sessions + accountingLock sync.RWMutex // lock for data consistency in accounting-related functions + balances map[enode.ID]int64 // map of balances for each peer + balancesLock sync.RWMutex // lock for balances map + cheques map[enode.ID]*Cheque // map of cheques for each peer + chequesLock sync.RWMutex // lock for cheques map + peers map[enode.ID]*Peer // map of all swap Peers + peersLock sync.RWMutex // lock for peers map + backend contract.Backend // the backend (blockchain) used + owner *Owner // contract access + params *Params // economic and operational parameters + contract swap.Contract // reference to the smart contract + disconnectThreshold int64 // default amount at which a peer + thresholdOracle ThresholdOracle + honeyPriceOracle HoneyOracle } // Owner encapsulates information related to accessing the contract @@ -88,16 +88,16 @@ func NewParams() *Params { // New - swap constructor func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Address, backend contract.Backend, disconnectThreshold int64, paymentThreshold int64) *Swap { return &Swap{ - store: stateStore, - balances: make(map[enode.ID]int64), - cheques: make(map[enode.ID]*Cheque), - peers: make(map[enode.ID]*Peer), - backend: backend, - owner: createOwner(prvkey, contract), - params: NewParams(), - defaultDisconnectThreshold: disconnectThreshold, - defaultThresholdOracle: NewThresholdOracle(paymentThreshold), - defaultHoneyPriceOracle: NewHoneyPriceOracle(), + store: stateStore, + balances: make(map[enode.ID]int64), + cheques: make(map[enode.ID]*Cheque), + peers: make(map[enode.ID]*Peer), + backend: backend, + owner: createOwner(prvkey, contract), + params: NewParams(), + disconnectThreshold: disconnectThreshold, + thresholdOracle: NewThresholdOracle(paymentThreshold), + honeyPriceOracle: NewHoneyPriceOracle(), } } @@ -158,7 +158,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { if !exists { return fmt.Errorf("peer %v does not exist", peer.ID()) } - disconnectThreshold := s.peers[peer.ID()].disconnectThreshold + disconnectThreshold := s.disconnectThreshold if balance >= disconnectThreshold { return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) } @@ -172,7 +172,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - paymentThreshold, _ := s.peers[peer.ID()].paymentThresholdOracle.GetPaymentThreshold() + paymentThreshold, _ := s.thresholdOracle.GetPaymentThreshold() if newBalance <= -paymentThreshold { log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) @@ -292,7 +292,7 @@ func (s *Swap) processAndVerifyCheque(cheque *Cheque, p *Peer) (uint64, error) { lastCheque := s.loadLastReceivedCheque(p) // TODO: there should probably be a lock here? - expectedAmount, err := p.honeyOracle.GetPrice(cheque.Honey) + expectedAmount, err := s.honeyPriceOracle.GetPrice(cheque.Honey) if err != nil { return 0, err } @@ -393,7 +393,7 @@ func (s *Swap) createCheque(swapPeer *Peer) (*Cheque, error) { honey := uint64(-peerBalance) var amount uint64 - amount, err = swapPeer.honeyOracle.GetPrice(honey) + amount, err = s.honeyPriceOracle.GetPrice(honey) if err != nil { return nil, fmt.Errorf("error getting price from oracle: %s", err.Error()) } From 60d5a567956826f538504b03a8e968d688ff4f55 Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 5 Sep 2019 13:48:21 +0200 Subject: [PATCH 06/39] cmd/swarm/main: swapFlagsOverride --- api/config.go | 4 ++-- cmd/swarm/config.go | 18 ++++++++++++------ cmd/swarm/config_test.go | 17 ++++++++++++++--- cmd/swarm/flags.go | 4 ++-- cmd/swarm/main.go | 3 +++ swap/config.go | 8 +++++--- swap/swap.go | 8 ++++---- swap/swap_test.go | 7 ++----- swap/thresholdOracle.go | 8 ++++---- swarm.go | 4 ++-- 10 files changed, 50 insertions(+), 31 deletions(-) diff --git a/api/config.go b/api/config.go index 6b81d1be40..eedfe2771c 100644 --- a/api/config.go +++ b/api/config.go @@ -55,8 +55,8 @@ type Config struct { // Swap configs SwapBackendURL string SwapEnabled bool - SwapPaymentThreshold int64 - SwapDisconnectThreshold int64 + SwapPaymentThreshold uint64 + SwapDisconnectThreshold uint64 *network.HiveParams Pss *pss.Params diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index 993e772dde..2bfdf31836 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -30,7 +30,6 @@ import ( cli "gopkg.in/urfave/cli.v1" "github.com/ethereum/go-ethereum/cmd/utils" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/naoina/toml" @@ -179,10 +178,6 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi currentConfig.BzzAccount = keyid } - if chbookaddr := ctx.GlobalString(ChequebookAddrFlag.Name); chbookaddr != "" { - currentConfig.Contract = common.HexToAddress(chbookaddr) - } - if networkid := ctx.GlobalString(SwarmNetworkIdFlag.Name); networkid != "" { id, err := strconv.ParseUint(networkid, 10, 64) if err != nil { @@ -212,6 +207,18 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi currentConfig.SwapEnabled = true } + if swapBackendURL := ctx.GlobalString(SwarmSwapBackendURLFlag.Name); swapBackendURL != "" { + currentConfig.SwapBackendURL = swapBackendURL + } + + if paymentThreshold := ctx.GlobalUint64(SwarmSwapPaymentThresholdFlag.Name); paymentThreshold != 0 { + currentConfig.SwapPaymentThreshold = paymentThreshold + } + + if disconnectThreshold := ctx.GlobalUint64(SwarmSwapDisconnectThresholdFlag.Name); disconnectThreshold != 0 { + currentConfig.SwapDisconnectThreshold = disconnectThreshold + } + if ctx.GlobalIsSet(SwarmSyncDisabledFlag.Name) { currentConfig.SyncEnabled = false } @@ -231,7 +238,6 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi currentConfig.DeliverySkipCheck = true } - currentConfig.SwapBackendURL = ctx.GlobalString(SwarmSwapBackendURLFlag.Name) if currentConfig.SwapEnabled && currentConfig.SwapBackendURL == "" { utils.Fatalf(SwarmErrSwapSetNoBackendURL) } diff --git a/cmd/swarm/config_test.go b/cmd/swarm/config_test.go index e68d3748ca..e251eba2d3 100644 --- a/cmd/swarm/config_test.go +++ b/cmd/swarm/config_test.go @@ -234,7 +234,7 @@ func TestConfigCmdLineOverrides(t *testing.T) { } flags := []string{ - fmt.Sprintf("--%s", SwarmNetworkIdFlag.Name), "42", + fmt.Sprintf("--%s", SwarmNetworkIdFlag.Name), "5", fmt.Sprintf("--%s", SwarmPortFlag.Name), httpPort, fmt.Sprintf("--%s", utils.ListenPortFlag.Name), "0", fmt.Sprintf("--%s", SwarmSyncDisabledFlag.Name), @@ -244,7 +244,10 @@ func TestConfigCmdLineOverrides(t *testing.T) { fmt.Sprintf("--%s", EnsAPIFlag.Name), "", fmt.Sprintf("--%s", utils.DataDirFlag.Name), dir, fmt.Sprintf("--%s", utils.IPCPathFlag.Name), conf.IPCPath, + fmt.Sprintf("--%s", SwarmSwapPaymentThresholdFlag.Name), "10", + fmt.Sprintf("--%s", SwarmSwapDisconnectThresholdFlag.Name), "15", } + node.Cmd = runSwarm(t, flags...) node.Cmd.InputLine(testPassphrase) defer func() { @@ -273,8 +276,8 @@ func TestConfigCmdLineOverrides(t *testing.T) { t.Fatalf("Expected port to be %s, got %s", httpPort, info.Port) } - if info.NetworkID != 42 { - t.Fatalf("Expected network ID to be %d, got %d", 42, info.NetworkID) + if info.NetworkID != 5 { + t.Fatalf("Expected network ID to be %d, got %d", 5, info.NetworkID) } if info.SyncEnabled { @@ -289,6 +292,14 @@ func TestConfigCmdLineOverrides(t *testing.T) { t.Fatalf("Expected Cors flag to be set to %s, got %s", "*", info.Cors) } + if info.SwapPaymentThreshold != 10 { + t.Fatalf("Expected SwapPaymentThreshold to be %d, but got %d", 10, info.SwapPaymentThreshold) + } + + if info.SwapDisconnectThreshold != 15 { + t.Fatalf("Expected SwapDisconnectThreshold to be %d, but got %d", 15, info.SwapDisconnectThreshold) + } + node.Shutdown() } diff --git a/cmd/swarm/flags.go b/cmd/swarm/flags.go index 13f64d7fae..4808d9660b 100644 --- a/cmd/swarm/flags.go +++ b/cmd/swarm/flags.go @@ -65,12 +65,12 @@ var ( Usage: "URL of the Ethereum API provider to use to settle SWAP payments", EnvVar: SwarmEnvSwapBackendURL, } - SwarmEnvSwapPaymentThresholdFlag = cli.Int64Flag{ + SwarmSwapPaymentThresholdFlag = cli.Uint64Flag{ Name: "swap-payment-threshold", Usage: "honey amount indebted to a peer at which you will initiate payment", EnvVar: SwarmEnvSwapPaymentThreshold, } - SwarmEnvDisconnectThresholdFlag = cli.Int64Flag{ + SwarmSwapDisconnectThresholdFlag = cli.Uint64Flag{ Name: "swap-disconnect-threshold", Usage: "honey amount at debt of a peer at which you will disconnect", EnvVar: SwarmEnvSwapDisconnectThreshold, diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index e514bfab6b..96c38c9be1 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -177,8 +177,11 @@ func init() { CorsStringFlag, EnsAPIFlag, SwarmTomlConfigPathFlag, + //swap flags SwarmSwapEnabledFlag, SwarmSwapBackendURLFlag, + SwarmSwapDisconnectThresholdFlag, + SwarmSwapPaymentThresholdFlag, SwarmSyncDisabledFlag, SwarmSyncUpdateDelay, SwarmMaxStreamPeerServersFlag, diff --git a/swap/config.go b/swap/config.go index 833a1a0470..b7112d274d 100644 --- a/swap/config.go +++ b/swap/config.go @@ -16,7 +16,9 @@ package swap -import "time" +import ( + "time" +) // These are currently arbitrary values which have not been verified nor tested // Need experimentation to arrive to values which make sense @@ -34,6 +36,6 @@ const ( // The smart-contract allows for setting this variable differently per beneficiary defaultHarddepositTimeoutDuration = 24 * time.Hour - // While Swap is unstable, it's only allowed to be run under a specific network ID - AllowedNetworkID = 5 + // While Swap is unstable, it is not allowed to run on mainnet + NonAllowedNetworkID = 1 ) diff --git a/swap/swap.go b/swap/swap.go index 6ca0c17bdf..fa3e697c70 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -60,7 +60,7 @@ type Swap struct { owner *Owner // contract access params *Params // economic and operational parameters contract swap.Contract // reference to the smart contract - disconnectThreshold int64 // default amount at which a peer + disconnectThreshold uint64 // default amount at which a peer thresholdOracle ThresholdOracle honeyPriceOracle HoneyOracle } @@ -86,7 +86,7 @@ func NewParams() *Params { } // New - swap constructor -func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Address, backend contract.Backend, disconnectThreshold int64, paymentThreshold int64) *Swap { +func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Address, backend contract.Backend, disconnectThreshold uint64, paymentThreshold uint64) *Swap { return &Swap{ store: stateStore, balances: make(map[enode.ID]int64), @@ -159,7 +159,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { return fmt.Errorf("peer %v does not exist", peer.ID()) } disconnectThreshold := s.disconnectThreshold - if balance >= disconnectThreshold { + if balance >= int64(disconnectThreshold) { return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) } @@ -174,7 +174,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // that the balance is *below* the threshold paymentThreshold, _ := s.thresholdOracle.GetPaymentThreshold() - if newBalance <= -paymentThreshold { + if newBalance <= -int64(paymentThreshold) { log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) swapPeer, ok := s.getPeer(peer.ID()) if !ok { diff --git a/swap/swap_test.go b/swap/swap_test.go index 5dd28bc5af..bbed035ac9 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -431,7 +431,7 @@ func calculateExpectedBalances(swap *Swap, bookings []booking) map[enode.ID]int6 peerID := booking.peer.ID() peerBalance := expectedBalances[peerID] // balance is not expected to be affected once past the disconnect threshold - if peerBalance < swap.peers[peerID].disconnectThreshold { + if peerBalance < int64(swap.disconnectThreshold) { peerBalance += booking.amount } expectedBalances[peerID] = peerBalance @@ -524,10 +524,7 @@ func newTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, func()) { // creates a dummy swap.Peer func newDummyPeer(spec *protocols.Spec) *Peer { return &Peer{ - Peer: newDummyProtocolPeer(spec), - paymentThresholdOracle: NewThresholdOracle(DefaultPaymentThreshold), - disconnectThreshold: DefaultDisconnectThreshold, - honeyOracle: NewHoneyPriceOracle(), + Peer: newDummyProtocolPeer(spec), } } diff --git a/swap/thresholdOracle.go b/swap/thresholdOracle.go index 1cfbd3a1f9..54804dea61 100644 --- a/swap/thresholdOracle.go +++ b/swap/thresholdOracle.go @@ -18,12 +18,12 @@ package swap // ThresholdOracle is the interface through which Oracles will deliver payment thresholds type ThresholdOracle interface { - GetPaymentThreshold() (int64, error) + GetPaymentThreshold() (uint64, error) } // NewThresholdOracle returns the actual oracle to be used for discovering the threshold // It will return a default one -func NewThresholdOracle(price int64) ThresholdOracle { +func NewThresholdOracle(price uint64) ThresholdOracle { return &fixedPaymentThreshold{ paymentThreshold: price, } @@ -31,10 +31,10 @@ func NewThresholdOracle(price int64) ThresholdOracle { // FixedPaymentThreshold is a paymentThreshold oracle which which returns a fixed price type fixedPaymentThreshold struct { - paymentThreshold int64 + paymentThreshold uint64 } // GetPrice returns the actual price for honey -func (fpo *fixedPaymentThreshold) GetPaymentThreshold() (int64, error) { +func (fpo *fixedPaymentThreshold) GetPaymentThreshold() (uint64, error) { return fpo.paymentThreshold, nil } diff --git a/swarm.go b/swarm.go index 37c3751b1e..ee0479960e 100644 --- a/swarm.go +++ b/swarm.go @@ -114,8 +114,8 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e // Swap initialization if config.SwapEnabled { // for now, Swap can only be enabled in a whitelisted network - if self.config.NetworkID != swap.AllowedNetworkID { - return nil, fmt.Errorf("swap can only be enabled under Network ID %d, found Network ID %d instead", swap.AllowedNetworkID, self.config.NetworkID) + if self.config.NetworkID == swap.NonAllowedNetworkID { + return nil, fmt.Errorf("swap can not be allowed under Network ID %d", swap.NonAllowedNetworkID) } // if Swap is enabled, we MUST have a contract API if self.config.SwapBackendURL == "" { From aa69db6fd9ad12b2196f23219aeaeee748312d46 Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 5 Sep 2019 14:21:34 +0200 Subject: [PATCH 07/39] swap: AllowedNetworkID => DisabledNetworkID --- swap/config.go | 2 +- swarm.go | 4 ++-- swarm_test.go | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/swap/config.go b/swap/config.go index b7112d274d..82616665bb 100644 --- a/swap/config.go +++ b/swap/config.go @@ -37,5 +37,5 @@ const ( defaultHarddepositTimeoutDuration = 24 * time.Hour // While Swap is unstable, it is not allowed to run on mainnet - NonAllowedNetworkID = 1 + DisabledNetworkID = 1 ) diff --git a/swarm.go b/swarm.go index ee0479960e..5ac33352f6 100644 --- a/swarm.go +++ b/swarm.go @@ -114,8 +114,8 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e // Swap initialization if config.SwapEnabled { // for now, Swap can only be enabled in a whitelisted network - if self.config.NetworkID == swap.NonAllowedNetworkID { - return nil, fmt.Errorf("swap can not be allowed under Network ID %d", swap.NonAllowedNetworkID) + if self.config.NetworkID == swap.DisabledNetworkID { + return nil, fmt.Errorf("swap can not be allowed under Network ID %d", swap.DisabledNetworkID) } // if Swap is enabled, we MUST have a contract API if self.config.SwapBackendURL == "" { diff --git a/swarm_test.go b/swarm_test.go index 1ad19c7118..1c0022e013 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethersphere/swarm/api" "github.com/ethersphere/swarm/sctx" - "github.com/ethersphere/swarm/swap" ) // TestNewSwarm validates Swarm fields in repsect to the provided configuration. @@ -114,7 +113,7 @@ func TestNewSwarm(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = ipcEndpoint config.SwapEnabled = true - config.NetworkID = swap.AllowedNetworkID + config.NetworkID = 2 }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s.backend == nil { @@ -220,7 +219,7 @@ func TestNewSwarmFailure(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = "" config.SwapEnabled = true - config.NetworkID = swap.AllowedNetworkID + config.NetworkID = 2 }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s != nil { From 4460d9aa8303acace346f4065d19c8921db7c756 Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 5 Sep 2019 15:47:00 +0200 Subject: [PATCH 08/39] swarm: updated TestNewSwarmFailure --- swarm_test.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/swarm_test.go b/swarm_test.go index 1c0022e013..786664dac0 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -17,6 +17,7 @@ package swarm import ( + "github.com/ethersphere/swarm/swap" "context" "encoding/hex" "io/ioutil" @@ -27,9 +28,6 @@ import ( "strings" "testing" "time" - - "github.com/ethersphere/swarm/network" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" @@ -228,11 +226,11 @@ func TestNewSwarmFailure(t *testing.T) { }, }, { - name: "with swap enabled and default network ID", + name: "with swap enabled and disabled networkID", configure: func(config *api.Config) { config.SwapBackendURL = ipcEndpoint config.SwapEnabled = true - config.NetworkID = network.DefaultNetworkID + config.NetworkID = swap.DisabledNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s != nil { From db83c9e022bd781f64a99b7dd3ea89397789eea2 Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 5 Sep 2019 16:33:41 +0200 Subject: [PATCH 09/39] cmd/swarm, swap: reverted unneeded changes --- cmd/swarm/config.go | 5 ++++- cmd/swarm/config_test.go | 6 +++--- swap/config.go | 4 +--- swap/swap.go | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index 2bfdf31836..bd4e4558fb 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -28,6 +28,7 @@ import ( "unicode" cli "gopkg.in/urfave/cli.v1" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/log" @@ -177,7 +178,9 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi if keyid := ctx.GlobalString(SwarmAccountFlag.Name); keyid != "" { currentConfig.BzzAccount = keyid } - + if chbookaddr := ctx.GlobalString(ChequebookAddrFlag.Name); chbookaddr != "" { + currentConfig.Contract = common.HexToAddress(chbookaddr) + } if networkid := ctx.GlobalString(SwarmNetworkIdFlag.Name); networkid != "" { id, err := strconv.ParseUint(networkid, 10, 64) if err != nil { diff --git a/cmd/swarm/config_test.go b/cmd/swarm/config_test.go index e251eba2d3..e6a129dd9c 100644 --- a/cmd/swarm/config_test.go +++ b/cmd/swarm/config_test.go @@ -234,7 +234,7 @@ func TestConfigCmdLineOverrides(t *testing.T) { } flags := []string{ - fmt.Sprintf("--%s", SwarmNetworkIdFlag.Name), "5", + fmt.Sprintf("--%s", SwarmNetworkIdFlag.Name), "42", fmt.Sprintf("--%s", SwarmPortFlag.Name), httpPort, fmt.Sprintf("--%s", utils.ListenPortFlag.Name), "0", fmt.Sprintf("--%s", SwarmSyncDisabledFlag.Name), @@ -276,8 +276,8 @@ func TestConfigCmdLineOverrides(t *testing.T) { t.Fatalf("Expected port to be %s, got %s", httpPort, info.Port) } - if info.NetworkID != 5 { - t.Fatalf("Expected network ID to be %d, got %d", 5, info.NetworkID) + if info.NetworkID != 42 { + t.Fatalf("Expected network ID to be %d, got %d", 42, info.NetworkID) } if info.SyncEnabled { diff --git a/swap/config.go b/swap/config.go index 82616665bb..45abe974d5 100644 --- a/swap/config.go +++ b/swap/config.go @@ -16,9 +16,7 @@ package swap -import ( - "time" -) +import "time" // These are currently arbitrary values which have not been verified nor tested // Need experimentation to arrive to values which make sense diff --git a/swap/swap.go b/swap/swap.go index fa3e697c70..5c4295eb98 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -60,9 +60,9 @@ type Swap struct { owner *Owner // contract access params *Params // economic and operational parameters contract swap.Contract // reference to the smart contract - disconnectThreshold uint64 // default amount at which a peer - thresholdOracle ThresholdOracle - honeyPriceOracle HoneyOracle + disconnectThreshold uint64 // amount at which the node will disconnect from the peer + thresholdOracle ThresholdOracle // oracle which resolves at which amount node will initiate payment + honeyPriceOracle HoneyOracle // oracle which resolves the price of honey (in Wei) } // Owner encapsulates information related to accessing the contract From df154dc727d053357f83632f3ec37cf292b5fec9 Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 5 Sep 2019 17:46:29 +0200 Subject: [PATCH 10/39] cmd, swap, swarm: gofmt --- cmd/swarm/config.go | 6 +++--- swap/swap.go | 4 ++-- swarm_test.go | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index bd4e4558fb..1778c5d424 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -27,8 +27,8 @@ import ( "strings" "unicode" - cli "gopkg.in/urfave/cli.v1" "github.com/ethereum/go-ethereum/common" + cli "gopkg.in/urfave/cli.v1" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/log" @@ -178,8 +178,8 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi if keyid := ctx.GlobalString(SwarmAccountFlag.Name); keyid != "" { currentConfig.BzzAccount = keyid } - if chbookaddr := ctx.GlobalString(ChequebookAddrFlag.Name); chbookaddr != "" { - currentConfig.Contract = common.HexToAddress(chbookaddr) + if chbookaddr := ctx.GlobalString(ChequebookAddrFlag.Name); chbookaddr != "" { + currentConfig.Contract = common.HexToAddress(chbookaddr) } if networkid := ctx.GlobalString(SwarmNetworkIdFlag.Name); networkid != "" { id, err := strconv.ParseUint(networkid, 10, 64) diff --git a/swap/swap.go b/swap/swap.go index 5c4295eb98..cab62569f9 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -61,8 +61,8 @@ type Swap struct { params *Params // economic and operational parameters contract swap.Contract // reference to the smart contract disconnectThreshold uint64 // amount at which the node will disconnect from the peer - thresholdOracle ThresholdOracle // oracle which resolves at which amount node will initiate payment - honeyPriceOracle HoneyOracle // oracle which resolves the price of honey (in Wei) + thresholdOracle ThresholdOracle // oracle which resolves at which amount node will initiate payment + honeyPriceOracle HoneyOracle // oracle which resolves the price of honey (in Wei) } // Owner encapsulates information related to accessing the contract diff --git a/swarm_test.go b/swarm_test.go index 786664dac0..0a579095f4 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -17,9 +17,14 @@ package swarm import ( - "github.com/ethersphere/swarm/swap" "context" "encoding/hex" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethersphere/swarm/api" + "github.com/ethersphere/swarm/sctx" + "github.com/ethersphere/swarm/swap" "io/ioutil" "math/rand" "os" @@ -28,11 +33,6 @@ import ( "strings" "testing" "time" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethersphere/swarm/api" - "github.com/ethersphere/swarm/sctx" ) // TestNewSwarm validates Swarm fields in repsect to the provided configuration. From bb85b52ee004d1819e9d1bc1598110b0705f0a23 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 9 Sep 2019 11:02:08 +0200 Subject: [PATCH 11/39] swarm: goimports formatting --- swarm_test.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/swarm_test.go b/swarm_test.go index 0a579095f4..41f8fdba5f 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -19,12 +19,6 @@ package swarm import ( "context" "encoding/hex" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethersphere/swarm/api" - "github.com/ethersphere/swarm/sctx" - "github.com/ethersphere/swarm/swap" "io/ioutil" "math/rand" "os" @@ -33,6 +27,13 @@ import ( "strings" "testing" "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rpc" + "github.com/ethersphere/swarm/api" + "github.com/ethersphere/swarm/sctx" + "github.com/ethersphere/swarm/swap" ) // TestNewSwarm validates Swarm fields in repsect to the provided configuration. From ebd8314ef7b484e330c493a071125fd582741ce0 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 9 Sep 2019 12:49:47 +0200 Subject: [PATCH 12/39] api, cmd, swap: flag order and naming, removed paymentThresholdOracle --- api/config.go | 22 +++++++++++----------- cmd/swarm/config.go | 26 +------------------------- cmd/swarm/flags.go | 2 +- cmd/swarm/main.go | 3 ++- swap/swap.go | 12 ++++++------ swap/thresholdOracle.go | 40 ---------------------------------------- 6 files changed, 21 insertions(+), 84 deletions(-) delete mode 100644 swap/thresholdOracle.go diff --git a/api/config.go b/api/config.go index eedfe2771c..34e71d43e2 100644 --- a/api/config.go +++ b/api/config.go @@ -55,12 +55,12 @@ type Config struct { // Swap configs SwapBackendURL string SwapEnabled bool - SwapPaymentThreshold uint64 - SwapDisconnectThreshold uint64 + SwapPaymentThreshold uint64 // in Honey + SwapDisconnectThreshold uint64 // in Honey + Contract common.Address *network.HiveParams Pss *pss.Params - Contract common.Address EnsRoot common.Address EnsAPIs []string Path string @@ -89,23 +89,23 @@ func NewConfig() (c *Config) { c = &Config{ FileStoreParams: storage.NewFileStoreParams(), + SwapBackendURL: "", + SwapEnabled: false, + SwapPaymentThreshold: swap.DefaultPaymentThreshold, + SwapDisconnectThreshold: swap.DefaultDisconnectThreshold, HiveParams: network.NewHiveParams(), Pss: pss.NewParams(), + EnsRoot: ens.TestNetAddress, + EnsAPIs: nil, + Path: node.DefaultDataDir(), ListenAddr: DefaultHTTPListenAddr, Port: DefaultHTTPPort, - Path: node.DefaultDataDir(), - EnsAPIs: nil, - EnsRoot: ens.TestNetAddress, NetworkID: network.DefaultNetworkID, SyncEnabled: true, SyncingSkipCheck: false, - MaxStreamPeerServers: 10000, DeliverySkipCheck: true, + MaxStreamPeerServers: 10000, SyncUpdateDelay: 15 * time.Second, - SwapEnabled: false, - SwapBackendURL: "", - SwapPaymentThreshold: swap.DefaultPaymentThreshold, - SwapDisconnectThreshold: swap.DefaultDisconnectThreshold, } return diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index 1778c5d424..4a9c75bddf 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -178,7 +178,7 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi if keyid := ctx.GlobalString(SwarmAccountFlag.Name); keyid != "" { currentConfig.BzzAccount = keyid } - if chbookaddr := ctx.GlobalString(ChequebookAddrFlag.Name); chbookaddr != "" { + if chbookaddr := ctx.GlobalString(SwarmSwapChequebookAddrFlag.Name); chbookaddr != "" { currentConfig.Contract = common.HexToAddress(chbookaddr) } if networkid := ctx.GlobalString(SwarmNetworkIdFlag.Name); networkid != "" { @@ -190,61 +190,47 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi currentConfig.NetworkID = id } } - if ctx.GlobalIsSet(utils.DataDirFlag.Name) { if datadir := ctx.GlobalString(utils.DataDirFlag.Name); datadir != "" { currentConfig.Path = expandPath(datadir) } } - bzzport := ctx.GlobalString(SwarmPortFlag.Name) if len(bzzport) > 0 { currentConfig.Port = bzzport } - if bzzaddr := ctx.GlobalString(SwarmListenAddrFlag.Name); bzzaddr != "" { currentConfig.ListenAddr = bzzaddr } - if ctx.GlobalIsSet(SwarmSwapEnabledFlag.Name) { currentConfig.SwapEnabled = true } - if swapBackendURL := ctx.GlobalString(SwarmSwapBackendURLFlag.Name); swapBackendURL != "" { currentConfig.SwapBackendURL = swapBackendURL } - if paymentThreshold := ctx.GlobalUint64(SwarmSwapPaymentThresholdFlag.Name); paymentThreshold != 0 { currentConfig.SwapPaymentThreshold = paymentThreshold } - if disconnectThreshold := ctx.GlobalUint64(SwarmSwapDisconnectThresholdFlag.Name); disconnectThreshold != 0 { currentConfig.SwapDisconnectThreshold = disconnectThreshold } - if ctx.GlobalIsSet(SwarmSyncDisabledFlag.Name) { currentConfig.SyncEnabled = false } - if d := ctx.GlobalDuration(SwarmSyncUpdateDelay.Name); d > 0 { currentConfig.SyncUpdateDelay = d } - // any value including 0 is acceptable currentConfig.MaxStreamPeerServers = ctx.GlobalInt(SwarmMaxStreamPeerServersFlag.Name) - if ctx.GlobalIsSet(SwarmLightNodeEnabled.Name) { currentConfig.LightNodeEnabled = true } - if ctx.GlobalIsSet(SwarmDeliverySkipCheckFlag.Name) { currentConfig.DeliverySkipCheck = true } - if currentConfig.SwapEnabled && currentConfig.SwapBackendURL == "" { utils.Fatalf(SwarmErrSwapSetNoBackendURL) } - if ctx.GlobalIsSet(EnsAPIFlag.Name) { ensAPIs := ctx.GlobalStringSlice(EnsAPIFlag.Name) // preserve backward compatibility to disable ENS with --ens-api="" @@ -254,40 +240,30 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi for i := range ensAPIs { ensAPIs[i] = expandPath(ensAPIs[i]) } - currentConfig.EnsAPIs = ensAPIs } - if cors := ctx.GlobalString(CorsStringFlag.Name); cors != "" { currentConfig.Cors = cors } - if storePath := ctx.GlobalString(SwarmStorePath.Name); storePath != "" { currentConfig.ChunkDbPath = storePath } - if storeCapacity := ctx.GlobalUint64(SwarmStoreCapacity.Name); storeCapacity != 0 { currentConfig.DbCapacity = storeCapacity } - if ctx.GlobalIsSet(SwarmStoreCacheCapacity.Name) { currentConfig.CacheCapacity = ctx.GlobalUint(SwarmStoreCacheCapacity.Name) } - if ctx.GlobalIsSet(SwarmBootnodeModeFlag.Name) { currentConfig.BootnodeMode = ctx.GlobalBool(SwarmBootnodeModeFlag.Name) } - if ctx.GlobalIsSet(SwarmDisableAutoConnectFlag.Name) { currentConfig.DisableAutoConnect = ctx.GlobalBool(SwarmDisableAutoConnectFlag.Name) } - if ctx.GlobalIsSet(SwarmGlobalStoreAPIFlag.Name) { currentConfig.GlobalStoreAPI = ctx.GlobalString(SwarmGlobalStoreAPIFlag.Name) } - return currentConfig - } // dumpConfig is the dumpconfig command. diff --git a/cmd/swarm/flags.go b/cmd/swarm/flags.go index 4808d9660b..c413effcd5 100644 --- a/cmd/swarm/flags.go +++ b/cmd/swarm/flags.go @@ -20,7 +20,7 @@ package main import cli "gopkg.in/urfave/cli.v1" var ( - ChequebookAddrFlag = cli.StringFlag{ + SwarmSwapChequebookAddrFlag = cli.StringFlag{ Name: "chequebook", Usage: "chequebook contract address", EnvVar: SwarmEnvChequebookAddr, diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 96c38c9be1..ea215e6398 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -182,6 +182,8 @@ func init() { SwarmSwapBackendURLFlag, SwarmSwapDisconnectThresholdFlag, SwarmSwapPaymentThresholdFlag, + SwarmSwapChequebookAddrFlag, + // end of swap flags SwarmSyncDisabledFlag, SwarmSyncUpdateDelay, SwarmMaxStreamPeerServersFlag, @@ -192,7 +194,6 @@ func init() { SwarmAccountFlag, SwarmBzzKeyHexFlag, SwarmNetworkIdFlag, - ChequebookAddrFlag, // upload flags SwarmApiFlag, SwarmRecursiveFlag, diff --git a/swap/swap.go b/swap/swap.go index cab62569f9..163cb0753d 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -60,8 +60,8 @@ type Swap struct { owner *Owner // contract access params *Params // economic and operational parameters contract swap.Contract // reference to the smart contract - disconnectThreshold uint64 // amount at which the node will disconnect from the peer - thresholdOracle ThresholdOracle // oracle which resolves at which amount node will initiate payment + disconnectThreshold uint64 // amount of debt of a peer at which the node will disconnect + paymentThreshold uint64 // amount of debt to a peer at which the node will initiate payment honeyPriceOracle HoneyOracle // oracle which resolves the price of honey (in Wei) } @@ -96,7 +96,7 @@ func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, contract common.Addre owner: createOwner(prvkey, contract), params: NewParams(), disconnectThreshold: disconnectThreshold, - thresholdOracle: NewThresholdOracle(paymentThreshold), + paymentThreshold: paymentThreshold, honeyPriceOracle: NewHoneyPriceOracle(), } } @@ -158,8 +158,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { if !exists { return fmt.Errorf("peer %v does not exist", peer.ID()) } - disconnectThreshold := s.disconnectThreshold - if balance >= int64(disconnectThreshold) { + disconnectThreshold := int64(s.disconnectThreshold) + if balance >= disconnectThreshold { return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) } @@ -172,7 +172,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - paymentThreshold, _ := s.thresholdOracle.GetPaymentThreshold() + paymentThreshold := int64(s.paymentThreshold) if newBalance <= -int64(paymentThreshold) { log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) diff --git a/swap/thresholdOracle.go b/swap/thresholdOracle.go deleted file mode 100644 index 54804dea61..0000000000 --- a/swap/thresholdOracle.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package swap - -// ThresholdOracle is the interface through which Oracles will deliver payment thresholds -type ThresholdOracle interface { - GetPaymentThreshold() (uint64, error) -} - -// NewThresholdOracle returns the actual oracle to be used for discovering the threshold -// It will return a default one -func NewThresholdOracle(price uint64) ThresholdOracle { - return &fixedPaymentThreshold{ - paymentThreshold: price, - } -} - -// FixedPaymentThreshold is a paymentThreshold oracle which which returns a fixed price -type fixedPaymentThreshold struct { - paymentThreshold uint64 -} - -// GetPrice returns the actual price for honey -func (fpo *fixedPaymentThreshold) GetPaymentThreshold() (uint64, error) { - return fpo.paymentThreshold, nil -} From 2cf5475c21f94ac0b318b812d8a22595b06c4e03 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 9 Sep 2019 15:13:08 +0200 Subject: [PATCH 13/39] added tests --- swap/swap.go | 1 - swap/swap_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/swap/swap.go b/swap/swap.go index 163cb0753d..7f8aead8be 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -354,7 +354,6 @@ func (s *Swap) sendCheque(swapPeer *Peer) error { log.Info("sending cheque", "honey", cheque.Honey, "cumulativePayout", cheque.ChequeParams.CumulativePayout, "beneficiary", cheque.Beneficiary, "contract", cheque.Contract) s.setCheque(peer, cheque) - err = s.store.Put(sentChequeKey(peer), &cheque) if err != nil { return fmt.Errorf("error while storing the last cheque: %s", err.Error()) diff --git a/swap/swap_test.go b/swap/swap_test.go index bbed035ac9..deafbe56b9 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -28,6 +28,7 @@ import ( mrand "math/rand" "os" "reflect" + "strings" "testing" "time" @@ -291,6 +292,31 @@ func TestRepeatedBookings(t *testing.T) { verifyBookings(t, swap, append(bookings, mixedBookings...)) } +func TestDisconnectThreshold(t *testing.T) { + swap, clean := newTestSwap(t, ownerKey) + defer clean() + testPeer := newDummyPeer(Spec) + swap.peers[testPeer.Peer.ID()] = testPeer + swap.Add(DefaultDisconnectThreshold, testPeer.Peer) + err := swap.Add(1, testPeer.Peer) + if !strings.Contains(err.Error(), "disconnect threshold") { + t.Fatal(err) + } +} + +func TestPaymentThreshold(t *testing.T) { + swap, clean := newTestSwap(t, ownerKey) + defer clean() + testPeer := newDummyPeer(Spec) + swap.peers[testPeer.Peer.ID()] = testPeer + swap.Add(-DefaultPaymentThreshold, testPeer.Peer) + var cheque Cheque + swap.store.Close() + err := swap.store.Get(sentChequeKey(testPeer.Peer.ID()), cheque) + fmt.Println(err) + t.Fatal(cheque) +} + // TestResetBalance tests that balances are correctly reset // The test deploys creates swap instances for each node, // deploys simulated contracts, sets the balance of each From b6dea35653fba565b45ab69739c2106dea732509 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 09:16:17 +0200 Subject: [PATCH 14/39] swap: made TestPaymentThreshold run --- swap/swap.go | 4 ++-- swap/swap_test.go | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/swap/swap.go b/swap/swap.go index 7f8aead8be..99b93c450f 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -173,8 +173,7 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold paymentThreshold := int64(s.paymentThreshold) - - if newBalance <= -int64(paymentThreshold) { + if newBalance <= -paymentThreshold { log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) swapPeer, ok := s.getPeer(peer.ID()) if !ok { @@ -354,6 +353,7 @@ func (s *Swap) sendCheque(swapPeer *Peer) error { log.Info("sending cheque", "honey", cheque.Honey, "cumulativePayout", cheque.ChequeParams.CumulativePayout, "beneficiary", cheque.Beneficiary, "contract", cheque.Contract) s.setCheque(peer, cheque) + fmt.Println(sentChequeKey(peer)) err = s.store.Put(sentChequeKey(peer), &cheque) if err != nil { return fmt.Errorf("error while storing the last cheque: %s", err.Error()) diff --git a/swap/swap_test.go b/swap/swap_test.go index deafbe56b9..8df74b08e8 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -309,12 +309,13 @@ func TestPaymentThreshold(t *testing.T) { defer clean() testPeer := newDummyPeer(Spec) swap.peers[testPeer.Peer.ID()] = testPeer - swap.Add(-DefaultPaymentThreshold, testPeer.Peer) - var cheque Cheque - swap.store.Close() - err := swap.store.Get(sentChequeKey(testPeer.Peer.ID()), cheque) + err := swap.Add(-DefaultPaymentThreshold, testPeer.Peer) fmt.Println(err) - t.Fatal(cheque) + var cheque *Cheque + _ = swap.store.Get(sentChequeKey(testPeer.Peer.ID()), &cheque) + if cheque.CumulativePayout != DefaultPaymentThreshold { + t.Fatal() + } } // TestResetBalance tests that balances are correctly reset @@ -521,6 +522,7 @@ func testCashCheque(s *Swap, otherSwap cswap.Contract, opts *bind.TransactOpts, func newBaseTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, string) { t.Helper() dir, err := ioutil.TempDir("", "swap_test_store") + fmt.Println(dir) if err != nil { t.Fatal(err) } From 627fb777880afccaf452e36e2a0231704b34b435 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 12:36:03 +0200 Subject: [PATCH 15/39] swap: make complete incomplete merge in swap_test.go --- swap/swap_test.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 7cf68f7262..fe3a8e75e9 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -532,11 +532,7 @@ func newBaseTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, string) { } log.Debug("creating simulated backend") -<<<<<<< HEAD - swap := New(stateStore, key, common.Address{}, testBackend, DefaultDisconnectThreshold, DefaultPaymentThreshold) -======= - swap := New(stateStore, key, testBackend) ->>>>>>> master + swap := New(stateStore, key, testBackend, DefaultDisconnectThreshold, DefaultPaymentThreshold) return swap, dir } From a3b51377c6a9223322cc2076bbd68b7f57dad487 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 16:41:04 +0200 Subject: [PATCH 16/39] swarm, swap: set config.NetworkID to config.DefaultNetworkID, removed redundant fmt.Println() --- swap/swap.go | 1 - swap/swap_test.go | 2 ++ swarm_test.go | 5 +++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/swap/swap.go b/swap/swap.go index b2d8d3f3c9..6e679d53cf 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -352,7 +352,6 @@ func (s *Swap) sendCheque(swapPeer *Peer) error { log.Info("sending cheque", "honey", cheque.Honey, "cumulativePayout", cheque.ChequeParams.CumulativePayout, "beneficiary", cheque.Beneficiary, "contract", cheque.Contract) s.setCheque(peer, cheque) - fmt.Println(sentChequeKey(peer)) err = s.store.Put(sentChequeKey(peer), &cheque) if err != nil { return fmt.Errorf("error while storing the last cheque: %s", err.Error()) diff --git a/swap/swap_test.go b/swap/swap_test.go index fe3a8e75e9..2ad23d8eca 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -292,6 +292,7 @@ func TestRepeatedBookings(t *testing.T) { verifyBookings(t, swap, append(bookings, mixedBookings...)) } +//TestDisconnectThreshold tests that the disconnect threshold is reached when adding the DefaultDisconnectThreshold amount to the peers balance func TestDisconnectThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() @@ -304,6 +305,7 @@ func TestDisconnectThreshold(t *testing.T) { } } +//TestPaymentThreshold tests that the payment threshold is reached when substracting the DefaultPaymentThreshold amount from the peers balance func TestPaymentThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() diff --git a/swarm_test.go b/swarm_test.go index 41f8fdba5f..8edd3ecb50 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/rpc" "github.com/ethersphere/swarm/api" + "github.com/ethersphere/swarm/network" "github.com/ethersphere/swarm/sctx" "github.com/ethersphere/swarm/swap" ) @@ -112,7 +113,7 @@ func TestNewSwarm(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = ipcEndpoint config.SwapEnabled = true - config.NetworkID = 2 + config.NetworkID = network.DefaultNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s.backend == nil { @@ -218,7 +219,7 @@ func TestNewSwarmFailure(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = "" config.SwapEnabled = true - config.NetworkID = 2 + config.NetworkID = config.DefaultNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s != nil { From 70092e66cb3e4be44843fd455bdc30314c45e8ab Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 16:52:36 +0200 Subject: [PATCH 17/39] swap: removed redundant Prinln --- swap/swap_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 2ad23d8eca..5fb1b54b3d 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -524,7 +524,6 @@ func testCashCheque(s *Swap, otherSwap cswap.Contract, opts *bind.TransactOpts, func newBaseTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, string) { t.Helper() dir, err := ioutil.TempDir("", "swap_test_store") - fmt.Println(dir) if err != nil { t.Fatal(err) } From 33f0bc36e0fd31757890e59a45d4379f8c71bce7 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 19:16:06 +0200 Subject: [PATCH 18/39] swarm: config.DefaultNetworkID => network.DefaultNetworkID --- swarm_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swarm_test.go b/swarm_test.go index 8edd3ecb50..9c62c38a65 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -219,7 +219,7 @@ func TestNewSwarmFailure(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = "" config.SwapEnabled = true - config.NetworkID = config.DefaultNetworkID + config.NetworkID = network.DefaultNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s != nil { From db12380b12d7b735e58fa93b80f537f4252e4b8d Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 20:23:11 +0200 Subject: [PATCH 19/39] swap: removed Spec from argument to newDummyPeer and newDummyProtocolPeer --- swap/protocol_test.go | 4 ++-- swap/swap_test.go | 32 ++++++++++++++++---------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/swap/protocol_test.go b/swap/protocol_test.go index 64e08eff6b..b6691e05c6 100644 --- a/swap/protocol_test.go +++ b/swap/protocol_test.go @@ -204,7 +204,7 @@ func TestTriggerPaymentThreshold(t *testing.T) { defer cleanup() // create a dummy pper - cPeer := newDummyPeer(Spec) + cPeer := newDummyPeer() creditor := NewPeer(cPeer.Peer, debitorSwap, common.Address{}, common.Address{}) // set the creditor as peer into the debitor's swap debitorSwap.peers[creditor.ID()] = creditor @@ -259,7 +259,7 @@ func TestTriggerDisconnectThreshold(t *testing.T) { defer clean() // create a dummy pper - cPeer := newDummyPeer(Spec) + cPeer := newDummyPeer() debitor := NewPeer(cPeer.Peer, creditorSwap, common.Address{}, common.Address{}) // set the debitor as peer into the creditor's swap creditorSwap.peers[debitor.ID()] = debitor diff --git a/swap/swap_test.go b/swap/swap_test.go index 5fb1b54b3d..3cba520874 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -108,7 +108,7 @@ func TestPeerBalance(t *testing.T) { defer clean() // test for correct value - testPeer := newDummyPeer(Spec) + testPeer := newDummyPeer() swap.balances[testPeer.Peer.ID()] = 888 b, err := swap.Balance(testPeer.Peer.ID()) if err != nil { @@ -140,12 +140,12 @@ func TestAllBalances(t *testing.T) { } // test balance addition for peer - testPeer := newDummyPeer(Spec) + testPeer := newDummyPeer() swap.balances[testPeer.Peer.ID()] = 808 testBalances(t, swap, map[enode.ID]int64{testPeer.Peer.ID(): 808}) // test successive balance addition for peer - testPeer2 := newDummyPeer(Spec) + testPeer2 := newDummyPeer() swap.balances[testPeer2.Peer.ID()] = 909 testBalances(t, swap, map[enode.ID]int64{testPeer.Peer.ID(): 808, testPeer2.Peer.ID(): 909}) @@ -269,14 +269,14 @@ func TestRepeatedBookings(t *testing.T) { var bookings []booking // credits to peer 1 - testPeer := newDummyPeer(Spec) + testPeer := newDummyPeer() swap.peers[testPeer.Peer.ID()] = testPeer bookingAmount := int64(mrand.Intn(100)) bookingQuantity := 1 + mrand.Intn(10) testPeerBookings(t, swap, &bookings, bookingAmount, bookingQuantity, testPeer.Peer) // debits to peer 2 - testPeer2 := newDummyPeer(Spec) + testPeer2 := newDummyPeer() swap.peers[testPeer2.Peer.ID()] = testPeer2 bookingAmount = 0 - int64(mrand.Intn(100)) bookingQuantity = 1 + mrand.Intn(10) @@ -296,7 +296,7 @@ func TestRepeatedBookings(t *testing.T) { func TestDisconnectThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() - testPeer := newDummyPeer(Spec) + testPeer := newDummyPeer() swap.peers[testPeer.Peer.ID()] = testPeer swap.Add(DefaultDisconnectThreshold, testPeer.Peer) err := swap.Add(1, testPeer.Peer) @@ -309,7 +309,7 @@ func TestDisconnectThreshold(t *testing.T) { func TestPaymentThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() - testPeer := newDummyPeer(Spec) + testPeer := newDummyPeer() swap.peers[testPeer.Peer.ID()] = testPeer err := swap.Add(-DefaultPaymentThreshold, testPeer.Peer) fmt.Println(err) @@ -350,8 +350,8 @@ func TestResetBalance(t *testing.T) { // create Peer instances // NOTE: remember that these are peer instances representing each **a model of the remote peer** for every local node // so creditor is the model of the remote mode for the debitor! (and vice versa) - cPeer := newDummyPeer(Spec) - dPeer := newDummyPeer(Spec) + cPeer := newDummyPeer() + dPeer := newDummyPeer() creditor := NewPeer(cPeer.Peer, debitorSwap, creditorSwap.owner.address, debitorSwap.owner.Contract) debitor := NewPeer(dPeer.Peer, creditorSwap, debitorSwap.owner.address, debitorSwap.owner.Contract) @@ -479,7 +479,7 @@ func TestRestoreBalanceFromStateStore(t *testing.T) { swap, testDir := newBaseTestSwap(t, ownerKey) defer os.RemoveAll(testDir) - testPeer := newDummyPeer(Spec) + testPeer := newDummyPeer() swap.balances[testPeer.Peer.ID()] = -8888 tmpBalance := swap.balances[testPeer.Peer.ID()] @@ -551,17 +551,17 @@ func newTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, func()) { } // creates a dummy swap.Peer -func newDummyPeer(spec *protocols.Spec) *Peer { +func newDummyPeer() *Peer { return &Peer{ - Peer: newDummyProtocolPeer(spec), + Peer: newDummyProtocolPeer(), } } // creates a dummy protocols.Peer with dummy MsgReadWriter -func newDummyProtocolPeer(spec *protocols.Spec) *protocols.Peer { +func newDummyProtocolPeer() *protocols.Peer { id := adapters.RandomNodeConfig().ID rw := &dummyMsgRW{} - protoPeer := protocols.NewPeer(p2p.NewPeer(id, "testPeer", nil), rw, spec) + protoPeer := protocols.NewPeer(p2p.NewPeer(id, "testPeer", nil), rw, Spec) return protoPeer } @@ -863,7 +863,7 @@ func TestSaveAndLoadLastReceivedCheque(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() - testPeer := NewPeer(newDummyProtocolPeer(Spec), swap, common.Address{}, common.Address{}) + testPeer := NewPeer(newDummyProtocolPeer(), swap, common.Address{}, common.Address{}) testCheque := newTestCheque() if err := swap.saveLastReceivedCheque(testPeer, testCheque); err != nil { @@ -888,7 +888,7 @@ func newTestSwapAndPeer(t *testing.T, key *ecdsa.PrivateKey) (*Swap, *Peer, func swap, clean := newTestSwap(t, key) // owner address is the beneficiary (counterparty) for the peer // that's because we expect cheques we receive to be signed by the address we would issue cheques to - peer := NewPeer(newDummyProtocolPeer(Spec), swap, ownerAddress, testChequeContract) + peer := NewPeer(newDummyProtocolPeer(), swap, ownerAddress, testChequeContract) // we need to adjust the owner address on swap because we will issue cheques to beneficiaryAddress swap.owner.address = beneficiaryAddress return swap, peer, clean From 5d7e68aba59e167123fd887cdeeef232458e5601 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 10 Sep 2019 22:38:34 +0200 Subject: [PATCH 20/39] swap: fix misspelling --- swap/swap_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 3cba520874..5604c6c721 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -305,7 +305,7 @@ func TestDisconnectThreshold(t *testing.T) { } } -//TestPaymentThreshold tests that the payment threshold is reached when substracting the DefaultPaymentThreshold amount from the peers balance +//TestPaymentThreshold tests that the payment threshold is reached when subtracting the DefaultPaymentThreshold amount from the peers balance func TestPaymentThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() From ff20676f32c46c01ea42c973fd8512c1034b6b46 Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 09:46:54 +0200 Subject: [PATCH 21/39] api: commenting exported vars, swap: remove redundant vars --- api/config.go | 11 ++++++----- swap/swap.go | 10 ++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/api/config.go b/api/config.go index 34e71d43e2..faf3be3457 100644 --- a/api/config.go +++ b/api/config.go @@ -53,11 +53,12 @@ type Config struct { BaseKey []byte // Swap configs - SwapBackendURL string - SwapEnabled bool - SwapPaymentThreshold uint64 // in Honey - SwapDisconnectThreshold uint64 // in Honey - Contract common.Address + SwapBackendURL string // Ethereum API endpoint + SwapEnabled bool // whether SWAP incentives are enabled + SwapPaymentThreshold uint64 // balance in Honey that a peer owes from us at which payment will be initiated to peer + SwapDisconnectThreshold uint64 // balance in Honey that we owe from a peer at which the node disconnects + Contract common.Address // address of the chequebook contract + // end of Swap configs *network.HiveParams Pss *pss.Params diff --git a/swap/swap.go b/swap/swap.go index 6e679d53cf..72c5e5d608 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -157,9 +157,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { if !exists { return fmt.Errorf("peer %v does not exist", peer.ID()) } - disconnectThreshold := int64(s.disconnectThreshold) - if balance >= disconnectThreshold { - return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) + if balance >= int64(s.disconnectThreshold) { + return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), int64(s.disconnectThreshold)) } var newBalance int64 @@ -171,9 +170,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - paymentThreshold := int64(s.paymentThreshold) - if newBalance <= -paymentThreshold { - log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) + if newBalance <= -int64(s.paymentThreshold) { + log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", s.paymentThreshold) swapPeer, ok := s.getPeer(peer.ID()) if !ok { return fmt.Errorf("peer %s not found", peer) From a1e0845426738eb8d53692fc0cc95a8edaf6aff2 Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 10:27:21 +0200 Subject: [PATCH 22/39] reverted allowedNetworkID/disabledNetworkID change --- swap/config.go | 5 ++--- swarm.go | 4 ++-- swarm_test.go | 8 ++++---- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/swap/config.go b/swap/config.go index 45abe974d5..9673c6d5a6 100644 --- a/swap/config.go +++ b/swap/config.go @@ -33,7 +33,6 @@ const ( // This is the amount of time in seconds which an issuer has to wait to decrease the harddeposit of a beneficiary. // The smart-contract allows for setting this variable differently per beneficiary defaultHarddepositTimeoutDuration = 24 * time.Hour - - // While Swap is unstable, it is not allowed to run on mainnet - DisabledNetworkID = 1 + // While Swap is unstable, it's only allowed to be run under a specific network ID (use the --bzznetworkid flag to set it) + AllowedNetworkID = 5 ) diff --git a/swarm.go b/swarm.go index d55c28d546..2123dfd978 100644 --- a/swarm.go +++ b/swarm.go @@ -114,8 +114,8 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e // Swap initialization if config.SwapEnabled { // for now, Swap can only be enabled in a whitelisted network - if self.config.NetworkID == swap.DisabledNetworkID { - return nil, fmt.Errorf("swap can not be allowed under Network ID %d", swap.DisabledNetworkID) + if self.config.NetworkID != swap.AllowedNetworkID { + return nil, fmt.Errorf("swap can only be enabled under BZZ Network ID %d, found Network ID %d instead", swap.AllowedNetworkID, self.config.NetworkID) } // if Swap is enabled, we MUST have a contract API if self.config.SwapBackendURL == "" { diff --git a/swarm_test.go b/swarm_test.go index 9c62c38a65..25886a3d75 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -113,7 +113,7 @@ func TestNewSwarm(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = ipcEndpoint config.SwapEnabled = true - config.NetworkID = network.DefaultNetworkID + config.NetworkID = swap.AllowedNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s.backend == nil { @@ -219,7 +219,7 @@ func TestNewSwarmFailure(t *testing.T) { configure: func(config *api.Config) { config.SwapBackendURL = "" config.SwapEnabled = true - config.NetworkID = network.DefaultNetworkID + config.NetworkID = swap.AllowedNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s != nil { @@ -228,11 +228,11 @@ func TestNewSwarmFailure(t *testing.T) { }, }, { - name: "with swap enabled and disabled networkID", + name: "with swap enabled and default network ID", configure: func(config *api.Config) { config.SwapBackendURL = ipcEndpoint config.SwapEnabled = true - config.NetworkID = swap.DisabledNetworkID + config.NetworkID = network.DefaultNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { if s != nil { From 068e1dd3f84bbae1ba91a5a35690206b8e8771dc Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 12:44:42 +0200 Subject: [PATCH 23/39] swarm, swap: SWAP integrity checks to NewSWAP, added check for disconnect/payment threshold --- cmd/swarm/config.go | 3 - cmd/swarm/config_test.go | 13 ---- cmd/swarm/main.go | 3 +- swap/swap.go | 29 +++++++++ swap/swap_test.go | 128 ++++++++++++++++++++++++++++++++++++++- swarm.go | 26 +++----- swarm_test.go | 1 + 7 files changed, 166 insertions(+), 37 deletions(-) diff --git a/cmd/swarm/config.go b/cmd/swarm/config.go index 4a9c75bddf..e7e4783ea4 100644 --- a/cmd/swarm/config.go +++ b/cmd/swarm/config.go @@ -228,9 +228,6 @@ func flagsOverride(currentConfig *bzzapi.Config, ctx *cli.Context) *bzzapi.Confi if ctx.GlobalIsSet(SwarmDeliverySkipCheckFlag.Name) { currentConfig.DeliverySkipCheck = true } - if currentConfig.SwapEnabled && currentConfig.SwapBackendURL == "" { - utils.Fatalf(SwarmErrSwapSetNoBackendURL) - } if ctx.GlobalIsSet(EnsAPIFlag.Name) { ensAPIs := ctx.GlobalStringSlice(EnsAPIFlag.Name) // preserve backward compatibility to disable ENS with --ens-api="" diff --git a/cmd/swarm/config_test.go b/cmd/swarm/config_test.go index e6a129dd9c..8fd55b2464 100644 --- a/cmd/swarm/config_test.go +++ b/cmd/swarm/config_test.go @@ -47,19 +47,6 @@ func TestConfigDump(t *testing.T) { swarm.ExpectExit() } -func TestConfigFailsSwapEnabledNoBackendURL(t *testing.T) { - flags := []string{ - fmt.Sprintf("--%s", SwarmNetworkIdFlag.Name), "42", - fmt.Sprintf("--%s", SwarmPortFlag.Name), "54545", - fmt.Sprintf("--%s", utils.ListenPortFlag.Name), "0", - fmt.Sprintf("--%s", SwarmSwapEnabledFlag.Name), - } - - swarm := runSwarm(t, flags...) - swarm.Expect("Fatal: " + SwarmErrSwapSetNoBackendURL + "\n") - swarm.ExpectExit() -} - func TestBzzKeyFlag(t *testing.T) { key, err := crypto.GenerateKey() if err != nil { diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index ea215e6398..2d7de27e5d 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -78,8 +78,7 @@ var gitCommit string //declare a few constant error messages, useful for later error check comparisons in test var ( - SwarmErrNoBZZAccount = "bzzaccount option is required but not set; check your config file, command line or environment variables" - SwarmErrSwapSetNoBackendURL = "SWAP is enabled but --swap-backend-url is not set" + SwarmErrNoBZZAccount = "bzzaccount option is required but not set; check your config file, command line or environment variables" ) // this help command gets added to any subcommand that does not define it explicitly diff --git a/swap/swap.go b/swap/swap.go index 72c5e5d608..87cf405007 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -23,6 +23,7 @@ import ( "errors" "fmt" "math/big" + "path/filepath" "strconv" "sync" "time" @@ -31,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethersphere/swarm/contracts/swap" contract "github.com/ethersphere/swarm/contracts/swap" @@ -101,6 +103,33 @@ func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Back } } +// NewSWAP - swap constructor +func NewSWAP(dbPath string, prvkey *ecdsa.PrivateKey, backendURL string, disconnectThreshold uint64, paymentThreshold uint64) (*Swap, error) { + // we MUST have a backend + if backendURL == "" { + return nil, errors.New("swap init error: no backend URL given") + } + log.Info("connecting to SWAP API", "url", backendURL) + // initialize the balances store + stateStore, err := state.NewDBStore(filepath.Join(dbPath, "swap.db")) + if err != nil { + return nil, fmt.Errorf("swap init error: %s", err) + } + if disconnectThreshold < paymentThreshold { + return nil, fmt.Errorf("swap init error: disconnect threshold lower than payment threshold. DisconnectThreshold: %d, PaymentThreshold: %d", disconnectThreshold, paymentThreshold) + } + backend, err := ethclient.Dial(backendURL) + if err != nil { + return nil, fmt.Errorf("swap init error: error connecting to Ethereum API %s: %s", backendURL, err) + } + return new( + stateStore, + prvkey, + backend, + disconnectThreshold, + paymentThreshold), nil +} + const ( balancePrefix = "balance_" sentChequePrefix = "sent_cheque_" diff --git a/swap/swap_test.go b/swap/swap_test.go index 5604c6c721..7725c15b87 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -20,6 +20,8 @@ import ( "bytes" "context" "crypto/ecdsa" + "crypto/rand" + "encoding/hex" "encoding/json" "flag" "fmt" @@ -27,7 +29,9 @@ import ( "math/big" mrand "math/rand" "os" + "path" "reflect" + "runtime" "strings" "testing" "time" @@ -42,6 +46,7 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/simulations/adapters" + "github.com/ethereum/go-ethereum/rpc" contract "github.com/ethersphere/go-sw3/contracts-v0-1-0/simpleswap" cswap "github.com/ethersphere/swarm/contracts/swap" "github.com/ethersphere/swarm/p2p/protocols" @@ -292,6 +297,127 @@ func TestRepeatedBookings(t *testing.T) { verifyBookings(t, swap, append(bookings, mixedBookings...)) } +func TestNewSwapFailure(t *testing.T) { + dir, err := ioutil.TempDir("", "swarm") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + // a simple rpc endpoint for testing dialing + ipcEndpoint := path.Join(dir, "TestSwarm.ipc") + + // windows namedpipes are not on filesystem but on NPFS + if runtime.GOOS == "windows" { + b := make([]byte, 8) + rand.Read(b) + ipcEndpoint = `\\.\pipe\TestSwarm-` + hex.EncodeToString(b) + } + + _, server, err := rpc.StartIPCEndpoint(ipcEndpoint, nil) + if err != nil { + t.Error(err) + } + defer server.Stop() + + prvKey, err := crypto.GenerateKey() + if err != nil { + t.Error(err) + } + + type SWAPConfig struct { + dbPath string + prvkey *ecdsa.PrivateKey + backendURL string + disconnectThreshold uint64 + paymentThreshold uint64 + } + + var config SWAPConfig + + for _, tc := range []struct { + name string + configure func(*SWAPConfig) + check func(*testing.T, *SWAPConfig) + }{ + { + name: "no backedURL", + configure: func(config *SWAPConfig) { + config.dbPath = dir + config.prvkey = prvKey + config.backendURL = "" + config.disconnectThreshold = DefaultDisconnectThreshold + config.paymentThreshold = DefaultPaymentThreshold + }, + check: func(t *testing.T, config *SWAPConfig) { + defer os.RemoveAll(config.dbPath) + _, err := NewSWAP( + config.dbPath, + config.prvkey, + config.backendURL, + config.disconnectThreshold, + config.paymentThreshold, + ) + if !strings.Contains(err.Error(), "no backend URL given") { + t.Fatal("no backendURL, but created SWAP") + } + }, + }, + { + name: "disconnect threshold lower than payment threshold", + configure: func(config *SWAPConfig) { + config.dbPath = dir + config.prvkey = prvKey + config.backendURL = ipcEndpoint + config.disconnectThreshold = DefaultDisconnectThreshold + config.paymentThreshold = DefaultDisconnectThreshold + 1 + }, + check: func(t *testing.T, config *SWAPConfig) { + defer os.RemoveAll(config.dbPath) + _, err := NewSWAP( + config.dbPath, + config.prvkey, + config.backendURL, + config.disconnectThreshold, + config.paymentThreshold, + ) + if !strings.Contains(err.Error(), "swap init error: disconnect threshold lower than payment threshold.") { + t.Fatal("disconnect threshold lower than payment threshold, but created SWAP") + } + }, + }, + { + name: "invalid backendURL", + configure: func(config *SWAPConfig) { + config.dbPath = dir + config.prvkey = prvKey + config.backendURL = "invalid backendURL" + config.disconnectThreshold = DefaultDisconnectThreshold + config.paymentThreshold = DefaultDisconnectThreshold + }, + check: func(t *testing.T, config *SWAPConfig) { + _, err := NewSWAP( + config.dbPath, + config.prvkey, + config.backendURL, + config.disconnectThreshold, + config.paymentThreshold, + ) + if !strings.Contains(err.Error(), "swap init error: error connecting to Ethereum API") { + t.Fatal("invalid backendURL, but created SWAP", err) + } + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + tc.configure(&config) + if tc.check != nil { + tc.check(t, &config) + } + }) + + } +} + //TestDisconnectThreshold tests that the disconnect threshold is reached when adding the DefaultDisconnectThreshold amount to the peers balance func TestDisconnectThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) @@ -533,7 +659,7 @@ func newBaseTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, string) { } log.Debug("creating simulated backend") - swap := New(stateStore, key, testBackend, DefaultDisconnectThreshold, DefaultPaymentThreshold) + swap := new(stateStore, key, testBackend, DefaultDisconnectThreshold, DefaultPaymentThreshold) return swap, dir } diff --git a/swarm.go b/swarm.go index 2123dfd978..e795556b15 100644 --- a/swarm.go +++ b/swarm.go @@ -117,29 +117,19 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e if self.config.NetworkID != swap.AllowedNetworkID { return nil, fmt.Errorf("swap can only be enabled under BZZ Network ID %d, found Network ID %d instead", swap.AllowedNetworkID, self.config.NetworkID) } - // if Swap is enabled, we MUST have a contract API - if self.config.SwapBackendURL == "" { - return nil, errors.New("swap enabled but no contract address given; fatal error condition, aborting") - } - log.Info("connecting to SWAP API", "url", self.config.SwapBackendURL) - self.backend, err = ethclient.Dial(self.config.SwapBackendURL) - if err != nil { - return nil, fmt.Errorf("error connecting to SWAP API %s: %s", self.config.SwapBackendURL, err) - } - - // initialize the balances store - swapStore, err := state.NewDBStore(filepath.Join(config.Path, "swap.db")) - if err != nil { - return nil, err - } + //TODO: is this needed here? + self.backend, _ = ethclient.Dial(self.config.SwapBackendURL) // create the accounting objects - self.swap = swap.New( - swapStore, + self.swap, err = swap.NewSWAP( + self.config.Path, self.privateKey, - self.backend, + self.config.SwapBackendURL, self.config.SwapDisconnectThreshold, self.config.SwapPaymentThreshold, ) + if err != nil { + return nil, err + } // start anonymous metrics collection self.accountingMetrics = protocols.SetupAccountingMetrics(10*time.Second, filepath.Join(config.Path, "metrics.db")) } diff --git a/swarm_test.go b/swarm_test.go index 25886a3d75..7422dbb685 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -185,6 +185,7 @@ func TestNewSwarm(t *testing.T) { } } +//TODO: is this still needed here, as we are validating all these fields now in SWAP // TestNewSwarmFailure validates that invalid Swarm fields in repsect to the provided configuration cause a failure. func TestNewSwarmFailure(t *testing.T) { dir, err := ioutil.TempDir("", "swarm") From f174f0da31eb877794846126410279e0dce2b13c Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 12:51:45 +0200 Subject: [PATCH 24/39] cmd/swarm: get rid of magical numbers and use DefaultPaymentThreshold/DefaultDisconnectThreshold --- cmd/swarm/config_test.go | 14 ++++++++------ swap/swap.go | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/cmd/swarm/config_test.go b/cmd/swarm/config_test.go index 8fd55b2464..a00e90301c 100644 --- a/cmd/swarm/config_test.go +++ b/cmd/swarm/config_test.go @@ -24,6 +24,7 @@ import ( "net" "os" "os/exec" + "strconv" "testing" "time" @@ -34,6 +35,7 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/ethersphere/swarm" "github.com/ethersphere/swarm/api" + "github.com/ethersphere/swarm/swap" ) func TestConfigDump(t *testing.T) { @@ -231,8 +233,8 @@ func TestConfigCmdLineOverrides(t *testing.T) { fmt.Sprintf("--%s", EnsAPIFlag.Name), "", fmt.Sprintf("--%s", utils.DataDirFlag.Name), dir, fmt.Sprintf("--%s", utils.IPCPathFlag.Name), conf.IPCPath, - fmt.Sprintf("--%s", SwarmSwapPaymentThresholdFlag.Name), "10", - fmt.Sprintf("--%s", SwarmSwapDisconnectThresholdFlag.Name), "15", + fmt.Sprintf("--%s", SwarmSwapPaymentThresholdFlag.Name), strconv.Itoa(swap.DefaultDisconnectThreshold), + fmt.Sprintf("--%s", SwarmSwapDisconnectThresholdFlag.Name), strconv.Itoa(swap.DefaultPaymentThreshold), } node.Cmd = runSwarm(t, flags...) @@ -279,12 +281,12 @@ func TestConfigCmdLineOverrides(t *testing.T) { t.Fatalf("Expected Cors flag to be set to %s, got %s", "*", info.Cors) } - if info.SwapPaymentThreshold != 10 { - t.Fatalf("Expected SwapPaymentThreshold to be %d, but got %d", 10, info.SwapPaymentThreshold) + if info.SwapPaymentThreshold != swap.DefaultPaymentThreshold { + t.Fatalf("Expected SwapPaymentThreshold to be %d, but got %d", swap.DefaultPaymentThreshold, info.SwapPaymentThreshold) } - if info.SwapDisconnectThreshold != 15 { - t.Fatalf("Expected SwapDisconnectThreshold to be %d, but got %d", 15, info.SwapDisconnectThreshold) + if info.SwapDisconnectThreshold != swap.DefaultDisconnectThreshold { + t.Fatalf("Expected SwapDisconnectThreshold to be %d, but got %d", swap.DefaultDisconnectThreshold, info.SwapDisconnectThreshold) } node.Shutdown() diff --git a/swap/swap.go b/swap/swap.go index 87cf405007..2bc81b8250 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -88,7 +88,7 @@ func NewParams() *Params { } // New - swap constructor -func New(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Backend, disconnectThreshold uint64, paymentThreshold uint64) *Swap { +func new(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Backend, disconnectThreshold uint64, paymentThreshold uint64) *Swap { return &Swap{ store: stateStore, balances: make(map[enode.ID]int64), From 5227f7a6b3d3aa4ed75dd018f773e9ea65352180 Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 13:02:42 +0200 Subject: [PATCH 25/39] swap: updated comment of NewSWAP --- swap/swap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/swap.go b/swap/swap.go index 2bc81b8250..3a84d144ac 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -103,7 +103,7 @@ func new(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Back } } -// NewSWAP - swap constructor +// NewSWAP - swap constructor with integrity checks func NewSWAP(dbPath string, prvkey *ecdsa.PrivateKey, backendURL string, disconnectThreshold uint64, paymentThreshold uint64) (*Swap, error) { // we MUST have a backend if backendURL == "" { From 0368a99f206686bab0a926bcaf8a3a889ef28c02 Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 17:25:50 +0200 Subject: [PATCH 26/39] swap: swap: call os.removeAll() in test, small refactor around payment/disconnect threshold --- swap/swap.go | 8 ++++---- swap/swap_test.go | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/swap/swap.go b/swap/swap.go index 730055db58..3395bef392 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -174,8 +174,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer is over the disconnect threshold balance := swapPeer.getBalance() - if balance >= int64(s.disconnectThreshold) { - return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), int64(s.disconnectThreshold)) + if disconnectThreshold := int64(s.disconnectThreshold); balance >= disconnectThreshold { + return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) } if err = swapPeer.updateBalance(amount); err != nil { @@ -185,8 +185,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - if swapPeer.getBalance() <= -int64(s.paymentThreshold) { - log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", s.paymentThreshold) + if paymentThreshold := int64(s.paymentThreshold); swapPeer.getBalance() <= -paymentThreshold { + log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) return swapPeer.sendCheque() } diff --git a/swap/swap_test.go b/swap/swap_test.go index a85d648c2e..b5840bf192 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -405,6 +405,7 @@ func TestNewSwapFailure(t *testing.T) { config.paymentThreshold = DefaultDisconnectThreshold }, check: func(t *testing.T, config *SWAPConfig) { + defer os.RemoveAll(config.dbPath) _, err := NewSWAP( config.dbPath, config.prvkey, From d652aa6a9684de0dd5ce37686bd4c8f1a809e4d9 Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 11 Sep 2019 17:44:11 +0200 Subject: [PATCH 27/39] swap: rename TempDir --- swap/swap_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index b5840bf192..37452049c5 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -308,13 +308,13 @@ func TestRepeatedBookings(t *testing.T) { } func TestNewSwapFailure(t *testing.T) { - dir, err := ioutil.TempDir("", "swarm") + dir, err := ioutil.TempDir("", "swarmSwap") if err != nil { t.Fatal(err) } defer os.RemoveAll(dir) // a simple rpc endpoint for testing dialing - ipcEndpoint := path.Join(dir, "TestSwarm.ipc") + ipcEndpoint := path.Join(dir, "TestSwarmSwap.ipc") // windows namedpipes are not on filesystem but on NPFS if runtime.GOOS == "windows" { From 782b83d55d32108dcbd0357434ec61adf4601cbe Mon Sep 17 00:00:00 2001 From: eknir Date: Thu, 12 Sep 2019 12:11:11 +0200 Subject: [PATCH 28/39] create new dir for every swapStore --- swap/swap_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 37452049c5..7f0ea5a3c7 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -382,7 +382,6 @@ func TestNewSwapFailure(t *testing.T) { config.paymentThreshold = DefaultDisconnectThreshold + 1 }, check: func(t *testing.T, config *SWAPConfig) { - defer os.RemoveAll(config.dbPath) _, err := NewSWAP( config.dbPath, config.prvkey, @@ -398,7 +397,6 @@ func TestNewSwapFailure(t *testing.T) { { name: "invalid backendURL", configure: func(config *SWAPConfig) { - config.dbPath = dir config.prvkey = prvKey config.backendURL = "invalid backendURL" config.disconnectThreshold = DefaultDisconnectThreshold @@ -420,6 +418,13 @@ func TestNewSwapFailure(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { + dir, err := ioutil.TempDir("", "swarmSwap") + if err != nil { + t.Fatal(err) + } + defer os.RemoveAll(dir) + config.dbPath = dir + tc.configure(&config) if tc.check != nil { tc.check(t, &config) From 63b04ab177a0ff659db1ca136aa64d7fe9afd1a0 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 16 Sep 2019 10:46:41 +0200 Subject: [PATCH 29/39] revert dummyPeer refactor --- swap/protocol_test.go | 4 ++-- swap/swap_test.go | 39 +++++++++++++++++++++++---------------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/swap/protocol_test.go b/swap/protocol_test.go index a3199413ef..1fd9e3df93 100644 --- a/swap/protocol_test.go +++ b/swap/protocol_test.go @@ -212,7 +212,7 @@ func TestTriggerPaymentThreshold(t *testing.T) { defer cleanup() // create a dummy pper - cPeer := newDummyPeer() + cPeer := newDummyPeerWithSpec(Spec) creditor, err := debitorSwap.addPeer(cPeer.Peer, common.Address{}, common.Address{}) if err != nil { t.Fatal(err) @@ -267,7 +267,7 @@ func TestTriggerDisconnectThreshold(t *testing.T) { defer clean() // create a dummy pper - cPeer := newDummyPeer() + cPeer := newDummyPeerWithSpec(Spec) debitor, err := creditorSwap.addPeer(cPeer.Peer, common.Address{}, common.Address{}) if err != nil { t.Fatal(err) diff --git a/swap/swap_test.go b/swap/swap_test.go index fee58c69a6..96d79d61f7 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -453,15 +453,17 @@ func TestPaymentThreshold(t *testing.T) { swap, clean := newTestSwap(t, ownerKey) defer clean() testDeploy(context.Background(), swap) - testPeer := newDummyPeer() + testPeer := newDummyPeerWithSpec(Spec) swap.addPeer(testPeer.Peer, swap.owner.address, swap.GetParams().ContractAddress) - err := swap.Add(-DefaultPaymentThreshold, testPeer.Peer) - fmt.Println(err, 1) - // var cheque *Cheque - // _ = swap.store.Get(sentChequeKey(testPeer.Peer.ID()), &cheque) - // if cheque.CumulativePayout != DefaultPaymentThreshold { - // t.Fatal() - // } + if err := swap.Add(-DefaultPaymentThreshold, testPeer.Peer); err != nil { + t.Fatal() + } + + var cheque *Cheque + _ = swap.store.Get(sentChequeKey(testPeer.Peer.ID()), &cheque) + if cheque.CumulativePayout != DefaultPaymentThreshold { + t.Fatal() + } } // TestResetBalance tests that balances are correctly reset @@ -702,19 +704,24 @@ func newTestSwap(t *testing.T, key *ecdsa.PrivateKey) (*Swap, func()) { return swap, clean } -// creates a dummy swap.Peer -func newDummyPeer() *Peer { - return &Peer{ - Peer: newDummyProtocolPeer(), - } +type dummyPeer struct { + *protocols.Peer } // creates a dummy protocols.Peer with dummy MsgReadWriter -func newDummyProtocolPeer() *protocols.Peer { +func newDummyPeer() *dummyPeer { + return newDummyPeerWithSpec(nil) +} + +// creates a dummy protocols.Peer with dummy MsgReadWriter +func newDummyPeerWithSpec(spec *protocols.Spec) *dummyPeer { id := adapters.RandomNodeConfig().ID rw := &dummyMsgRW{} - protoPeer := protocols.NewPeer(p2p.NewPeer(id, "testPeer", nil), rw, Spec) - return protoPeer + protoPeer := protocols.NewPeer(p2p.NewPeer(id, "testPeer", nil), rw, spec) + dummy := &dummyPeer{ + Peer: protoPeer, + } + return dummy } // creates cheque structure for testing From c0cc688e4978530c43cd246d940955854938eb92 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 16 Sep 2019 10:55:53 +0200 Subject: [PATCH 30/39] revert dummyPeer refactor --- swap/peer.go | 1 - swap/swap_test.go | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/swap/peer.go b/swap/peer.go index 6693d65a1e..debc23e85a 100644 --- a/swap/peer.go +++ b/swap/peer.go @@ -166,7 +166,6 @@ func (p *Peer) sendCheque() error { } log.Info("sending cheque", "honey", cheque.Honey, "cumulativePayout", cheque.ChequeParams.CumulativePayout, "beneficiary", cheque.Beneficiary, "contract", cheque.Contract) - return p.Send(context.Background(), &EmitChequeMsg{ Cheque: cheque, }) diff --git a/swap/swap_test.go b/swap/swap_test.go index 96d79d61f7..2cf6a242fc 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -481,9 +481,6 @@ func TestResetBalance(t *testing.T) { defer clean2() ctx := context.Background() - // deploying would strictly speaking not be necessary, as the signing would also just work - // with empty contract addresses. Nevertheless to avoid later suprises and for - // coherence and clarity we deploy here so that we get a simulated contract address err := testDeploy(ctx, creditorSwap) if err != nil { t.Fatal(err) @@ -496,8 +493,9 @@ func TestResetBalance(t *testing.T) { // create Peer instances // NOTE: remember that these are peer instances representing each **a model of the remote peer** for every local node // so creditor is the model of the remote mode for the debitor! (and vice versa) - cPeer := newDummyPeer() - dPeer := newDummyPeer() + cPeer := newDummyPeerWithSpec(Spec) + dPeer := newDummyPeerWithSpec(Spec) + fmt.Println(1) creditor, err := debitorSwap.addPeer(cPeer.Peer, creditorSwap.owner.address, debitorSwap.GetParams().ContractAddress) if err != nil { t.Fatal(err) From 2765e9feb9452cd7596fd12e81a8e01857e290a7 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 16 Sep 2019 11:45:55 +0200 Subject: [PATCH 31/39] swap, swarm, cmd/swarm: rename swap constructor, remove redundant tests in swarm, remove backend on swarm, correct test TestConfigCmdLineOverrides --- cmd/swarm/config_test.go | 13 +++++++------ swap/swap.go | 6 +++--- swarm.go | 6 +----- swarm_test.go | 24 ++++-------------------- 4 files changed, 15 insertions(+), 34 deletions(-) diff --git a/cmd/swarm/config_test.go b/cmd/swarm/config_test.go index aea040bd08..b0d77b34c2 100644 --- a/cmd/swarm/config_test.go +++ b/cmd/swarm/config_test.go @@ -238,8 +238,9 @@ func TestConfigCmdLineOverrides(t *testing.T) { fmt.Sprintf("--%s", EnsAPIFlag.Name), "", fmt.Sprintf("--%s", utils.DataDirFlag.Name), dir, fmt.Sprintf("--%s", utils.IPCPathFlag.Name), conf.IPCPath, - fmt.Sprintf("--%s", SwarmSwapPaymentThresholdFlag.Name), strconv.Itoa(swap.DefaultPaymentThreshold), - fmt.Sprintf("--%s", SwarmSwapDisconnectThresholdFlag.Name), strconv.Itoa(swap.DefaultDisconnectThreshold), + "--verbosity", fmt.Sprintf("%d", *testutil.Loglevel), + fmt.Sprintf("--%s", SwarmSwapPaymentThresholdFlag.Name), strconv.Itoa(swap.DefaultPaymentThreshold + 1), + fmt.Sprintf("--%s", SwarmSwapDisconnectThresholdFlag.Name), strconv.Itoa(swap.DefaultDisconnectThreshold + 1), } node.Cmd = runSwarm(t, flags...) @@ -286,12 +287,12 @@ func TestConfigCmdLineOverrides(t *testing.T) { t.Fatalf("Expected Cors flag to be set to %s, got %s", "*", info.Cors) } - if info.SwapPaymentThreshold != swap.DefaultPaymentThreshold { - t.Fatalf("Expected SwapPaymentThreshold to be %d, but got %d", swap.DefaultPaymentThreshold, info.SwapPaymentThreshold) + if info.SwapPaymentThreshold != (swap.DefaultPaymentThreshold + 1) { + t.Fatalf("Expected SwapPaymentThreshold to be %d, but got %d", swap.DefaultPaymentThreshold+1, info.SwapPaymentThreshold) } - if info.SwapDisconnectThreshold != swap.DefaultDisconnectThreshold { - t.Fatalf("Expected SwapDisconnectThreshold to be %d, but got %d", swap.DefaultDisconnectThreshold, info.SwapDisconnectThreshold) + if info.SwapDisconnectThreshold != (swap.DefaultDisconnectThreshold + 1) { + t.Fatalf("Expected SwapDisconnectThreshold to be %d, but got %d", swap.DefaultDisconnectThreshold+1, info.SwapDisconnectThreshold) } node.Shutdown() diff --git a/swap/swap.go b/swap/swap.go index 7eafdb4a72..e88a3b7942 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -80,7 +80,7 @@ func NewParams() *Params { } } -// New - swap constructor +// new - swap constructor without integrity check func new(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Backend, disconnectThreshold uint64, paymentThreshold uint64) *Swap { return &Swap{ store: stateStore, @@ -94,8 +94,8 @@ func new(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Back } } -// NewSWAP - swap constructor with integrity checks -func NewSWAP(dbPath string, prvkey *ecdsa.PrivateKey, backendURL string, disconnectThreshold uint64, paymentThreshold uint64) (*Swap, error) { +// New - swap constructor with integrity checks +func New(dbPath string, prvkey *ecdsa.PrivateKey, backendURL string, disconnectThreshold uint64, paymentThreshold uint64) (*Swap, error) { // we MUST have a backend if backendURL == "" { return nil, errors.New("swap init error: no backend URL given") diff --git a/swarm.go b/swarm.go index 8579ac56e3..303f112f4f 100644 --- a/swarm.go +++ b/swarm.go @@ -44,7 +44,6 @@ import ( "github.com/ethersphere/swarm/bzzeth" "github.com/ethersphere/swarm/chunk" "github.com/ethersphere/swarm/contracts/ens" - cswap "github.com/ethersphere/swarm/contracts/swap" "github.com/ethersphere/swarm/fuse" "github.com/ethersphere/swarm/log" "github.com/ethersphere/swarm/network" @@ -79,7 +78,6 @@ type Swarm struct { retrieval *retrieval.Retrieval bzz *network.Bzz // the logistic manager bzzEth *bzzeth.BzzEth - backend cswap.Backend privateKey *ecdsa.PrivateKey netStore *storage.NetStore sfs *fuse.SwarmFS // need this to cleanup all the active mounts on node exit @@ -119,10 +117,8 @@ func NewSwarm(config *api.Config, mockStore *mock.NodeStore) (self *Swarm, err e if self.config.NetworkID != swap.AllowedNetworkID { return nil, fmt.Errorf("swap can only be enabled under BZZ Network ID %d, found Network ID %d instead", swap.AllowedNetworkID, self.config.NetworkID) } - //TODO: is this needed here? - self.backend, _ = ethclient.Dial(self.config.SwapBackendURL) // create the accounting objects - self.swap, err = swap.NewSWAP( + self.swap, err = swap.New( self.config.Path, self.privateKey, self.config.SwapBackendURL, diff --git a/swarm_test.go b/swarm_test.go index efe2dfd101..2fdf45bc25 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -75,9 +75,6 @@ func TestNewSwarm(t *testing.T) { if s.config != config { t.Error("config is not the same object") } - if s.backend != nil { - t.Error("backend is not nil") - } if s.privateKey == nil { t.Error("private key is not set") } @@ -121,8 +118,8 @@ func TestNewSwarm(t *testing.T) { config.NetworkID = swap.AllowedNetworkID }, check: func(t *testing.T, s *Swarm, _ *api.Config) { - if s.backend == nil { - t.Error("backend is nil") + if s.swap == nil { + t.Error("swap is nil") } }, }, @@ -133,8 +130,8 @@ func TestNewSwarm(t *testing.T) { config.SwapEnabled = false }, check: func(t *testing.T, s *Swarm, _ *api.Config) { - if s.backend != nil { - t.Error("backend is not nil") + if s.swap != nil { + t.Error("swap is not nil") } }, }, @@ -220,19 +217,6 @@ func TestNewSwarmFailure(t *testing.T) { configure func(*api.Config) check func(*testing.T, *Swarm, *api.Config) }{ - { - name: "with swap enabled and api endpoint blank", - configure: func(config *api.Config) { - config.SwapBackendURL = "" - config.SwapEnabled = true - config.NetworkID = swap.AllowedNetworkID - }, - check: func(t *testing.T, s *Swarm, _ *api.Config) { - if s != nil { - t.Error("swarm struct is not nil") - } - }, - }, { name: "with swap enabled and default network ID", configure: func(config *api.Config) { From 0f753f2a4789da1e0a091ae4b2b54e52c7c09231 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 16 Sep 2019 11:46:47 +0200 Subject: [PATCH 32/39] swarm: remove TODO comment --- swarm_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/swarm_test.go b/swarm_test.go index 2fdf45bc25..ba4dc72e7a 100644 --- a/swarm_test.go +++ b/swarm_test.go @@ -187,7 +187,6 @@ func TestNewSwarm(t *testing.T) { } } -//TODO: is this still needed here, as we are validating all these fields now in SWAP // TestNewSwarmFailure validates that invalid Swarm fields in repsect to the provided configuration cause a failure. func TestNewSwarmFailure(t *testing.T) { dir, err := ioutil.TempDir("", "swarm") From c5edfc29a84e7942703bc7d9855d10712c2ac8d3 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 16 Sep 2019 12:14:46 +0200 Subject: [PATCH 33/39] swap: NewSWAP name update in test --- swap/swap_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 2cf6a242fc..f602d27e9e 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -360,7 +360,7 @@ func TestNewSwapFailure(t *testing.T) { }, check: func(t *testing.T, config *SWAPConfig) { defer os.RemoveAll(config.dbPath) - _, err := NewSWAP( + _, err := New( config.dbPath, config.prvkey, config.backendURL, @@ -382,7 +382,7 @@ func TestNewSwapFailure(t *testing.T) { config.paymentThreshold = DefaultDisconnectThreshold + 1 }, check: func(t *testing.T, config *SWAPConfig) { - _, err := NewSWAP( + _, err := New( config.dbPath, config.prvkey, config.backendURL, @@ -404,7 +404,7 @@ func TestNewSwapFailure(t *testing.T) { }, check: func(t *testing.T, config *SWAPConfig) { defer os.RemoveAll(config.dbPath) - _, err := NewSWAP( + _, err := New( config.dbPath, config.prvkey, config.backendURL, From acb3d890b8357ab015d2f253e336201832da3620 Mon Sep 17 00:00:00 2001 From: eknir Date: Mon, 16 Sep 2019 17:15:29 +0200 Subject: [PATCH 34/39] swap: rename of variable in test and code comments --- swap/config.go | 2 +- swap/swap.go | 4 ++-- swap/swap_test.go | 25 +++++++++++++------------ 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/swap/config.go b/swap/config.go index 9673c6d5a6..ee942ae0c5 100644 --- a/swap/config.go +++ b/swap/config.go @@ -33,6 +33,6 @@ const ( // This is the amount of time in seconds which an issuer has to wait to decrease the harddeposit of a beneficiary. // The smart-contract allows for setting this variable differently per beneficiary defaultHarddepositTimeoutDuration = 24 * time.Hour - // While Swap is unstable, it's only allowed to be run under a specific network ID (use the --bzznetworkid flag to set it) + // Until we deploy swap officially, it's only allowed to be enabled under a specific network ID (use the --bzznetworkid flag to set it) AllowedNetworkID = 5 ) diff --git a/swap/swap.go b/swap/swap.go index e88a3b7942..10987a0126 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -106,8 +106,8 @@ func New(dbPath string, prvkey *ecdsa.PrivateKey, backendURL string, disconnectT if err != nil { return nil, fmt.Errorf("swap init error: %s", err) } - if disconnectThreshold < paymentThreshold { - return nil, fmt.Errorf("swap init error: disconnect threshold lower than payment threshold. DisconnectThreshold: %d, PaymentThreshold: %d", disconnectThreshold, paymentThreshold) + if disconnectThreshold <= paymentThreshold { + return nil, fmt.Errorf("swap init error: disconnect threshold lower or at payment threshold. DisconnectThreshold: %d, PaymentThreshold: %d", disconnectThreshold, paymentThreshold) } backend, err := ethclient.Dial(backendURL) if err != nil { diff --git a/swap/swap_test.go b/swap/swap_test.go index f602d27e9e..38203f9111 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -307,6 +307,7 @@ func TestRepeatedBookings(t *testing.T) { verifyBookings(t, swap, append(bookings, mixedBookings...)) } +//TestNewSwapFailure attempt to initialze SWAP with (a combination of) parameters which are not allowed. The test checks whether there is indeed indeed fails func TestNewSwapFailure(t *testing.T) { dir, err := ioutil.TempDir("", "swarmSwap") if err != nil { @@ -334,7 +335,7 @@ func TestNewSwapFailure(t *testing.T) { t.Error(err) } - type SWAPConfig struct { + type testSwapConfig struct { dbPath string prvkey *ecdsa.PrivateKey backendURL string @@ -342,23 +343,23 @@ func TestNewSwapFailure(t *testing.T) { paymentThreshold uint64 } - var config SWAPConfig + var config testSwapConfig for _, tc := range []struct { name string - configure func(*SWAPConfig) - check func(*testing.T, *SWAPConfig) + configure func(*testSwapConfig) + check func(*testing.T, *testSwapConfig) }{ { name: "no backedURL", - configure: func(config *SWAPConfig) { + configure: func(config *testSwapConfig) { config.dbPath = dir config.prvkey = prvKey config.backendURL = "" config.disconnectThreshold = DefaultDisconnectThreshold config.paymentThreshold = DefaultPaymentThreshold }, - check: func(t *testing.T, config *SWAPConfig) { + check: func(t *testing.T, config *testSwapConfig) { defer os.RemoveAll(config.dbPath) _, err := New( config.dbPath, @@ -374,14 +375,14 @@ func TestNewSwapFailure(t *testing.T) { }, { name: "disconnect threshold lower than payment threshold", - configure: func(config *SWAPConfig) { + configure: func(config *testSwapConfig) { config.dbPath = dir config.prvkey = prvKey config.backendURL = ipcEndpoint config.disconnectThreshold = DefaultDisconnectThreshold config.paymentThreshold = DefaultDisconnectThreshold + 1 }, - check: func(t *testing.T, config *SWAPConfig) { + check: func(t *testing.T, config *testSwapConfig) { _, err := New( config.dbPath, config.prvkey, @@ -389,20 +390,20 @@ func TestNewSwapFailure(t *testing.T) { config.disconnectThreshold, config.paymentThreshold, ) - if !strings.Contains(err.Error(), "swap init error: disconnect threshold lower than payment threshold.") { + if !strings.Contains(err.Error(), "swap init error: disconnect threshold lower or at payment threshold.") { t.Fatal("disconnect threshold lower than payment threshold, but created SWAP") } }, }, { name: "invalid backendURL", - configure: func(config *SWAPConfig) { + configure: func(config *testSwapConfig) { config.prvkey = prvKey config.backendURL = "invalid backendURL" config.disconnectThreshold = DefaultDisconnectThreshold - config.paymentThreshold = DefaultDisconnectThreshold + config.paymentThreshold = DefaultPaymentThreshold }, - check: func(t *testing.T, config *SWAPConfig) { + check: func(t *testing.T, config *testSwapConfig) { defer os.RemoveAll(config.dbPath) _, err := New( config.dbPath, From b8d9c0bcf227a1b9c9f5262de71506ed16edac00 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 17 Sep 2019 12:11:29 +0200 Subject: [PATCH 35/39] made thresholds an int64 on the swap object --- swap/swap.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/swap/swap.go b/swap/swap.go index 10987a0126..8318f26722 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -57,8 +57,8 @@ type Swap struct { params *Params // economic and operational parameters contract swap.Contract // reference to the smart contract honeyPriceOracle HoneyOracle // oracle which resolves the price of honey (in Wei) - paymentThreshold uint64 // amount of debt to a peer at which the node will initiate payment - disconnectThreshold uint64 // amount of debt of a peer at which the node will disconnect + paymentThreshold int64 // amount of debt to a peer at which the node will initiate payment + disconnectThreshold int64 // amount of debt of a peer at which the node will disconnect } // Owner encapsulates information related to accessing the contract @@ -88,8 +88,8 @@ func new(stateStore state.Store, prvkey *ecdsa.PrivateKey, backend contract.Back backend: backend, owner: createOwner(prvkey), params: NewParams(), - disconnectThreshold: disconnectThreshold, - paymentThreshold: paymentThreshold, + disconnectThreshold: int64(disconnectThreshold), + paymentThreshold: int64(paymentThreshold), honeyPriceOracle: NewHoneyPriceOracle(), } } @@ -173,8 +173,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer is over the disconnect threshold balance := swapPeer.getBalance() - if disconnectThreshold := int64(s.disconnectThreshold); balance >= disconnectThreshold { - return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), disconnectThreshold) + if balance >= s.disconnectThreshold { + return fmt.Errorf("balance for peer %s is over the disconnect threshold %d, disconnecting", peer.ID().String(), s.disconnectThreshold) } if err = swapPeer.updateBalance(amount); err != nil { @@ -184,8 +184,8 @@ func (s *Swap) Add(amount int64, peer *protocols.Peer) (err error) { // Check if balance with peer crosses the payment threshold // It is the peer with a negative balance who sends a cheque, thus we check // that the balance is *below* the threshold - if paymentThreshold := int64(s.paymentThreshold); swapPeer.getBalance() <= -paymentThreshold { - log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", paymentThreshold) + if swapPeer.getBalance() <= -s.paymentThreshold { + log.Warn("balance for peer went over the payment threshold, sending cheque", "peer", peer.ID().String(), "payment threshold", s.paymentThreshold) return swapPeer.sendCheque() } From e6de6c89a3db2bc5823ba7ec7281edd481c9c332 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 17 Sep 2019 12:13:52 +0200 Subject: [PATCH 36/39] swap: grammatical correction TestNewSwapFailure comment --- swap/swap_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 38203f9111..99ffe816ea 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -307,7 +307,7 @@ func TestRepeatedBookings(t *testing.T) { verifyBookings(t, swap, append(bookings, mixedBookings...)) } -//TestNewSwapFailure attempt to initialze SWAP with (a combination of) parameters which are not allowed. The test checks whether there is indeed indeed fails +//TestNewSwapFailure attempts to initialze SWAP with (a combination of) parameters which are not allowed. The test checks whether there are indeed failures func TestNewSwapFailure(t *testing.T) { dir, err := ioutil.TempDir("", "swarmSwap") if err != nil { From d0a7bc419c2fe7ce1b6ee8a822ad57324c3544b0 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 17 Sep 2019 18:16:52 +0200 Subject: [PATCH 37/39] swap: removed int64 casting in tests --- swap/swap_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/swap_test.go b/swap/swap_test.go index 99ffe816ea..5f069bf375 100644 --- a/swap/swap_test.go +++ b/swap/swap_test.go @@ -610,7 +610,7 @@ func calculateExpectedBalances(swap *Swap, bookings []booking) map[enode.ID]int6 peerID := booking.peer.ID() peerBalance := expectedBalances[peerID] // balance is not expected to be affected once past the disconnect threshold - if peerBalance < int64(swap.disconnectThreshold) { + if peerBalance < swap.disconnectThreshold { peerBalance += booking.amount } expectedBalances[peerID] = peerBalance From bf928a230fc57189d0eb0de358cbdde746a37478 Mon Sep 17 00:00:00 2001 From: eknir Date: Tue, 17 Sep 2019 20:37:56 +0200 Subject: [PATCH 38/39] made comments w.r.t. flags from both peers point of view --- api/config.go | 4 ++-- cmd/swarm/flags.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/config.go b/api/config.go index faf3be3457..78d3fb66d9 100644 --- a/api/config.go +++ b/api/config.go @@ -55,8 +55,8 @@ type Config struct { // Swap configs SwapBackendURL string // Ethereum API endpoint SwapEnabled bool // whether SWAP incentives are enabled - SwapPaymentThreshold uint64 // balance in Honey that a peer owes from us at which payment will be initiated to peer - SwapDisconnectThreshold uint64 // balance in Honey that we owe from a peer at which the node disconnects + SwapPaymentThreshold uint64 // honey amount at which a payment is triggered + SwapDisconnectThreshold uint64 // honey amount at which a peer disconnects Contract common.Address // address of the chequebook contract // end of Swap configs diff --git a/cmd/swarm/flags.go b/cmd/swarm/flags.go index c413effcd5..6af8a59151 100644 --- a/cmd/swarm/flags.go +++ b/cmd/swarm/flags.go @@ -67,12 +67,12 @@ var ( } SwarmSwapPaymentThresholdFlag = cli.Uint64Flag{ Name: "swap-payment-threshold", - Usage: "honey amount indebted to a peer at which you will initiate payment", + Usage: "honey amount at which payment is triggered", EnvVar: SwarmEnvSwapPaymentThreshold, } SwarmSwapDisconnectThresholdFlag = cli.Uint64Flag{ Name: "swap-disconnect-threshold", - Usage: "honey amount at debt of a peer at which you will disconnect", + Usage: "honey amount at which a peer disconnects", EnvVar: SwarmEnvSwapDisconnectThreshold, } SwarmSyncDisabledFlag = cli.BoolTFlag{ From 49f0006db6e60da7db9261463a72084f61e978a3 Mon Sep 17 00:00:00 2001 From: eknir Date: Wed, 18 Sep 2019 09:48:31 +0200 Subject: [PATCH 39/39] changed last comment w.r.t.s threshold comment from both peers point of view --- swap/swap.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swap/swap.go b/swap/swap.go index 8318f26722..08052bd0cd 100644 --- a/swap/swap.go +++ b/swap/swap.go @@ -57,8 +57,8 @@ type Swap struct { params *Params // economic and operational parameters contract swap.Contract // reference to the smart contract honeyPriceOracle HoneyOracle // oracle which resolves the price of honey (in Wei) - paymentThreshold int64 // amount of debt to a peer at which the node will initiate payment - disconnectThreshold int64 // amount of debt of a peer at which the node will disconnect + paymentThreshold int64 // honey amount at which a payment is triggered + disconnectThreshold int64 // honey amount at which a peer disconnects } // Owner encapsulates information related to accessing the contract