Commit 273f120e authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

swap, accounting: move to bigint (#1187)

parent 7ac406d3
...@@ -193,15 +193,15 @@ func (c *command) setAllFlags(cmd *cobra.Command) { ...@@ -193,15 +193,15 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
cmd.Flags().String(optionNameVerbosity, "info", "log verbosity level 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace") cmd.Flags().String(optionNameVerbosity, "info", "log verbosity level 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace")
cmd.Flags().String(optionWelcomeMessage, "", "send a welcome message string during handshakes") cmd.Flags().String(optionWelcomeMessage, "", "send a welcome message string during handshakes")
cmd.Flags().Bool(optionNameGlobalPinningEnabled, false, "enable global pinning") cmd.Flags().Bool(optionNameGlobalPinningEnabled, false, "enable global pinning")
cmd.Flags().Uint64(optionNamePaymentThreshold, 100000, "threshold in BZZ where you expect to get paid from your peers") cmd.Flags().String(optionNamePaymentThreshold, "100000", "threshold in BZZ where you expect to get paid from your peers")
cmd.Flags().Uint64(optionNamePaymentTolerance, 10000, "excess debt above payment threshold in BZZ where you disconnect from your peer") cmd.Flags().String(optionNamePaymentTolerance, "10000", "excess debt above payment threshold in BZZ where you disconnect from your peer")
cmd.Flags().Uint64(optionNamePaymentEarly, 10000, "amount in BZZ below the peers payment threshold when we initiate settlement") cmd.Flags().String(optionNamePaymentEarly, "10000", "amount in BZZ below the peers payment threshold when we initiate settlement")
cmd.Flags().StringSlice(optionNameResolverEndpoints, []string{}, "ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url") cmd.Flags().StringSlice(optionNameResolverEndpoints, []string{}, "ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url")
cmd.Flags().Bool(optionNameGatewayMode, false, "disable a set of sensitive features in the api") cmd.Flags().Bool(optionNameGatewayMode, false, "disable a set of sensitive features in the api")
cmd.Flags().Bool(optionNameClefSignerEnable, false, "enable clef signer") cmd.Flags().Bool(optionNameClefSignerEnable, false, "enable clef signer")
cmd.Flags().String(optionNameClefSignerEndpoint, "", "clef signer endpoint") cmd.Flags().String(optionNameClefSignerEndpoint, "", "clef signer endpoint")
cmd.Flags().String(optionNameSwapEndpoint, "http://localhost:8545", "swap ethereum blockchain endpoint") cmd.Flags().String(optionNameSwapEndpoint, "http://localhost:8545", "swap ethereum blockchain endpoint")
cmd.Flags().String(optionNameSwapFactoryAddress, "", "swap factory address") cmd.Flags().String(optionNameSwapFactoryAddress, "", "swap factory address")
cmd.Flags().Uint64(optionNameSwapInitialDeposit, 100000000, "initial deposit if deploying a new chequebook") cmd.Flags().String(optionNameSwapInitialDeposit, "100000000", "initial deposit if deploying a new chequebook")
cmd.Flags().Bool(optionNameSwapEnable, true, "enable swap") cmd.Flags().Bool(optionNameSwapEnable, true, "enable swap")
} }
...@@ -137,14 +137,14 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz ...@@ -137,14 +137,14 @@ Welcome to the Swarm.... Bzzz Bzzzz Bzzzz
TracingServiceName: c.config.GetString(optionNameTracingServiceName), TracingServiceName: c.config.GetString(optionNameTracingServiceName),
Logger: logger, Logger: logger,
GlobalPinningEnabled: c.config.GetBool(optionNameGlobalPinningEnabled), GlobalPinningEnabled: c.config.GetBool(optionNameGlobalPinningEnabled),
PaymentThreshold: c.config.GetUint64(optionNamePaymentThreshold), PaymentThreshold: c.config.GetString(optionNamePaymentThreshold),
PaymentTolerance: c.config.GetUint64(optionNamePaymentTolerance), PaymentTolerance: c.config.GetString(optionNamePaymentTolerance),
PaymentEarly: c.config.GetUint64(optionNamePaymentEarly), PaymentEarly: c.config.GetString(optionNamePaymentEarly),
ResolverConnectionCfgs: resolverCfgs, ResolverConnectionCfgs: resolverCfgs,
GatewayMode: c.config.GetBool(optionNameGatewayMode), GatewayMode: c.config.GetBool(optionNameGatewayMode),
SwapEndpoint: c.config.GetString(optionNameSwapEndpoint), SwapEndpoint: c.config.GetString(optionNameSwapEndpoint),
SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress), SwapFactoryAddress: c.config.GetString(optionNameSwapFactoryAddress),
SwapInitialDeposit: c.config.GetUint64(optionNameSwapInitialDeposit), SwapInitialDeposit: c.config.GetString(optionNameSwapInitialDeposit),
SwapEnable: c.config.GetBool(optionNameSwapEnable), SwapEnable: c.config.GetBool(optionNameSwapEnable),
}) })
if err != nil { if err != nil {
......
...@@ -8,7 +8,7 @@ import ( ...@@ -8,7 +8,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math" "math/big"
"strings" "strings"
"sync" "sync"
"time" "time"
...@@ -42,22 +42,22 @@ type Interface interface { ...@@ -42,22 +42,22 @@ type Interface interface {
// Debit increases the balance we have with the peer (we get "paid" back). // Debit increases the balance we have with the peer (we get "paid" back).
Debit(peer swarm.Address, price uint64) error Debit(peer swarm.Address, price uint64) error
// Balance returns the current balance for the given peer. // Balance returns the current balance for the given peer.
Balance(peer swarm.Address) (int64, error) Balance(peer swarm.Address) (*big.Int, error)
// SurplusBalance returns the current surplus balance for the given peer. // SurplusBalance returns the current surplus balance for the given peer.
SurplusBalance(peer swarm.Address) (int64, error) SurplusBalance(peer swarm.Address) (*big.Int, error)
// Balances returns balances for all known peers. // Balances returns balances for all known peers.
Balances() (map[string]int64, error) Balances() (map[string]*big.Int, error)
// CompensatedBalance returns the current balance deducted by current surplus balance for the given peer. // CompensatedBalance returns the current balance deducted by current surplus balance for the given peer.
CompensatedBalance(peer swarm.Address) (int64, error) CompensatedBalance(peer swarm.Address) (*big.Int, error)
// CompensatedBalances returns the compensated balances for all known peers. // CompensatedBalances returns the compensated balances for all known peers.
CompensatedBalances() (map[string]int64, error) CompensatedBalances() (map[string]*big.Int, error)
} }
// accountingPeer holds all in-memory accounting information for one peer. // accountingPeer holds all in-memory accounting information for one peer.
type accountingPeer struct { type accountingPeer struct {
lock sync.Mutex // lock to be held during any accounting action for this peer lock sync.Mutex // lock to be held during any accounting action for this peer
reservedBalance uint64 // amount currently reserved for active peer interaction reservedBalance *big.Int // amount currently reserved for active peer interaction
paymentThreshold uint64 // the threshold at which the peer expects us to pay paymentThreshold *big.Int // the threshold at which the peer expects us to pay
} }
// Accounting is the main implementation of the accounting interface. // Accounting is the main implementation of the accounting interface.
...@@ -68,11 +68,11 @@ type Accounting struct { ...@@ -68,11 +68,11 @@ type Accounting struct {
logger logging.Logger logger logging.Logger
store storage.StateStorer store storage.StateStorer
// The payment threshold in BZZ we communicate to our peers. // The payment threshold in BZZ we communicate to our peers.
paymentThreshold uint64 paymentThreshold *big.Int
// The amount in BZZ we let peers exceed the payment threshold before we // The amount in BZZ we let peers exceed the payment threshold before we
// disconnect them. // disconnect them.
paymentTolerance uint64 paymentTolerance *big.Int
earlyPayment uint64 earlyPayment *big.Int
settlement settlement.Interface settlement settlement.Interface
pricing pricing.Interface pricing pricing.Interface
metrics metrics metrics metrics
...@@ -95,16 +95,12 @@ var ( ...@@ -95,16 +95,12 @@ var (
func NewAccounting( func NewAccounting(
PaymentThreshold, PaymentThreshold,
PaymentTolerance, PaymentTolerance,
EarlyPayment uint64, EarlyPayment *big.Int,
Logger logging.Logger, Logger logging.Logger,
Store storage.StateStorer, Store storage.StateStorer,
Settlement settlement.Interface, Settlement settlement.Interface,
Pricing pricing.Interface, Pricing pricing.Interface,
) (*Accounting, error) { ) (*Accounting, error) {
if PaymentTolerance+PaymentThreshold > math.MaxInt64 {
return nil, fmt.Errorf("tolerance plus threshold too big: %w", ErrOverflow)
}
return &Accounting{ return &Accounting{
accountingPeers: make(map[string]*accountingPeer), accountingPeers: make(map[string]*accountingPeer),
paymentThreshold: PaymentThreshold, paymentThreshold: PaymentThreshold,
...@@ -135,31 +131,22 @@ func (a *Accounting) Reserve(ctx context.Context, peer swarm.Address, price uint ...@@ -135,31 +131,22 @@ func (a *Accounting) Reserve(ctx context.Context, peer swarm.Address, price uint
} }
} }
// Check for safety of increase of reservedBalance by price bigPrice := new(big.Int).SetUint64(price)
if accountingPeer.reservedBalance+price < accountingPeer.reservedBalance { nextReserved := new(big.Int).Add(accountingPeer.reservedBalance, bigPrice)
return ErrOverflow
}
nextReserved := accountingPeer.reservedBalance + price expectedBalance := new(big.Int).Sub(currentBalance, nextReserved)
// Subtract already reserved amount from actual balance, to get expected balance
expectedBalance, err := subtractI64mU64(currentBalance, nextReserved)
if err != nil {
return err
}
// Determine if we will owe anything to the peer, if we owe less than 0, we conclude we owe nothing // Determine if we will owe anything to the peer, if we owe less than 0, we conclude we owe nothing
// This conversion is made safe by previous subtractI64mU64 not allowing MinInt64 expectedDebt := new(big.Int).Neg(expectedBalance)
expectedDebt := -expectedBalance if expectedDebt.Cmp(big.NewInt(0)) < 0 {
if expectedDebt < 0 { expectedDebt.SetInt64(0)
expectedDebt = 0
} }
threshold := accountingPeer.paymentThreshold threshold := new(big.Int).Set(accountingPeer.paymentThreshold)
if threshold > a.earlyPayment { if threshold.Cmp(a.earlyPayment) > 0 {
threshold -= a.earlyPayment threshold.Sub(threshold, a.earlyPayment)
} else { } else {
threshold = 0 threshold.SetInt64(0)
} }
additionalDebt, err := a.SurplusBalance(peer) additionalDebt, err := a.SurplusBalance(peer)
...@@ -168,35 +155,29 @@ func (a *Accounting) Reserve(ctx context.Context, peer swarm.Address, price uint ...@@ -168,35 +155,29 @@ func (a *Accounting) Reserve(ctx context.Context, peer swarm.Address, price uint
} }
// uint64 conversion of surplusbalance is safe because surplusbalance is always positive // uint64 conversion of surplusbalance is safe because surplusbalance is always positive
if additionalDebt < 0 { if additionalDebt.Cmp(big.NewInt(0)) < 0 {
return ErrInvalidValue return ErrInvalidValue
} }
increasedExpectedDebt, err := addI64pU64(expectedDebt, uint64(additionalDebt)) increasedExpectedDebt := new(big.Int).Add(expectedDebt, additionalDebt)
if err != nil {
return err
}
// If our expected debt is less than earlyPayment away from our payment threshold // If our expected debt is less than earlyPayment away from our payment threshold
// and we are actually in debt, trigger settlement. // and we are actually in debt, trigger settlement.
// we pay early to avoid needlessly blocking request later when concurrent requests occur and we are already close to the payment threshold. // we pay early to avoid needlessly blocking request later when concurrent requests occur and we are already close to the payment threshold.
if increasedExpectedDebt >= int64(threshold) && currentBalance < 0 { if increasedExpectedDebt.Cmp(threshold) >= 0 && currentBalance.Cmp(big.NewInt(0)) < 0 {
err = a.settle(ctx, peer, accountingPeer) err = a.settle(ctx, peer, accountingPeer)
if err != nil { if err != nil {
return fmt.Errorf("failed to settle with peer %v: %v", peer, err) return fmt.Errorf("failed to settle with peer %v: %v", peer, err)
} }
// if we settled successfully our balance is back at 0 // if we settled successfully our balance is back at 0
// and the expected debt therefore equals next reserved amount // and the expected debt therefore equals next reserved amount
expectedDebt = int64(nextReserved) expectedDebt = nextReserved
increasedExpectedDebt, err = addI64pU64(expectedDebt, uint64(additionalDebt)) increasedExpectedDebt = new(big.Int).Add(expectedDebt, additionalDebt)
if err != nil {
return err
}
} }
// if expectedDebt would still exceed the paymentThreshold at this point block this request // if expectedDebt would still exceed the paymentThreshold at this point block this request
// this can happen if there is a large number of concurrent requests to the same peer // this can happen if there is a large number of concurrent requests to the same peer
if increasedExpectedDebt > int64(accountingPeer.paymentThreshold) { if increasedExpectedDebt.Cmp(accountingPeer.paymentThreshold) > 0 {
a.metrics.AccountingBlocksCount.Inc() a.metrics.AccountingBlocksCount.Inc()
return ErrOverdraft return ErrOverdraft
} }
...@@ -216,12 +197,14 @@ func (a *Accounting) Release(peer swarm.Address, price uint64) { ...@@ -216,12 +197,14 @@ func (a *Accounting) Release(peer swarm.Address, price uint64) {
accountingPeer.lock.Lock() accountingPeer.lock.Lock()
defer accountingPeer.lock.Unlock() defer accountingPeer.lock.Unlock()
bigPrice := new(big.Int).SetUint64(price)
// NOTE: this should never happen if Reserve and Release calls are paired. // NOTE: this should never happen if Reserve and Release calls are paired.
if price > accountingPeer.reservedBalance { if bigPrice.Cmp(accountingPeer.reservedBalance) > 0 {
a.logger.Error("attempting to release more balance than was reserved for peer") a.logger.Error("attempting to release more balance than was reserved for peer")
accountingPeer.reservedBalance = 0 accountingPeer.reservedBalance.SetUint64(0)
} else { } else {
accountingPeer.reservedBalance -= price accountingPeer.reservedBalance.Sub(accountingPeer.reservedBalance, bigPrice)
} }
} }
...@@ -244,10 +227,7 @@ func (a *Accounting) Credit(peer swarm.Address, price uint64) error { ...@@ -244,10 +227,7 @@ func (a *Accounting) Credit(peer swarm.Address, price uint64) error {
} }
// Calculate next balance by safely decreasing current balance with the price we credit // Calculate next balance by safely decreasing current balance with the price we credit
nextBalance, err := subtractI64mU64(currentBalance, price) nextBalance := new(big.Int).Sub(currentBalance, new(big.Int).SetUint64(price))
if err != nil {
return err
}
a.logger.Tracef("crediting peer %v with price %d, new balance is %d", peer, price, nextBalance) a.logger.Tracef("crediting peer %v with price %d, new balance is %d", peer, price, nextBalance)
...@@ -274,23 +254,17 @@ func (a *Accounting) settle(ctx context.Context, peer swarm.Address, balance *ac ...@@ -274,23 +254,17 @@ func (a *Accounting) settle(ctx context.Context, peer swarm.Address, balance *ac
// Don't do anything if there is no actual debt. // Don't do anything if there is no actual debt.
// This might be the case if the peer owes us and the total reserve for a // This might be the case if the peer owes us and the total reserve for a
// peer exceeds the payment treshold. // peer exceeds the payment treshold.
if oldBalance >= 0 { if oldBalance.Cmp(big.NewInt(0)) >= 0 {
return nil return nil
} }
// check safety of the following -1 * int64 conversion, all negative int64 have positive int64 equals except MinInt64
if oldBalance == math.MinInt64 {
return ErrOverflow
}
// This is safe because of the earlier check for oldbalance < 0 and the check for != MinInt64 // This is safe because of the earlier check for oldbalance < 0 and the check for != MinInt64
paymentAmount := uint64(-oldBalance) paymentAmount := new(big.Int).Neg(oldBalance)
nextBalance := 0
// Try to save the next balance first. // Try to save the next balance first.
// Otherwise we might pay and then not be able to save, forcing us to pay // Otherwise we might pay and then not be able to save, forcing us to pay
// again after restart. // again after restart.
err = a.store.Put(peerBalanceKey(peer), nextBalance) err = a.store.Put(peerBalanceKey(peer), big.NewInt(0))
if err != nil { if err != nil {
return fmt.Errorf("failed to persist balance: %w", err) return fmt.Errorf("failed to persist balance: %w", err)
} }
...@@ -320,22 +294,19 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error { ...@@ -320,22 +294,19 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error {
accountingPeer.lock.Lock() accountingPeer.lock.Lock()
defer accountingPeer.lock.Unlock() defer accountingPeer.lock.Unlock()
cost := price cost := new(big.Int).SetUint64(price)
// see if peer has surplus balance to deduct this transaction of // see if peer has surplus balance to deduct this transaction of
surplusBalance, err := a.SurplusBalance(peer) surplusBalance, err := a.SurplusBalance(peer)
if err != nil { if err != nil {
return fmt.Errorf("failed to get surplus balance: %w", err) return fmt.Errorf("failed to get surplus balance: %w", err)
} }
if surplusBalance > 0 { if surplusBalance.Cmp(big.NewInt(0)) > 0 {
// get new surplus balance after deduct // get new surplus balance after deduct
newSurplusBalance, err := subtractI64mU64(surplusBalance, price) newSurplusBalance := new(big.Int).Sub(surplusBalance, cost)
if err != nil {
return err
}
// if nothing left for debiting, store new surplus balance and return from debit // if nothing left for debiting, store new surplus balance and return from debit
if newSurplusBalance >= 0 { if newSurplusBalance.Cmp(big.NewInt(0)) >= 0 {
a.logger.Tracef("surplus debiting peer %v with value %d, new surplus balance is %d", peer, price, newSurplusBalance) a.logger.Tracef("surplus debiting peer %v with value %d, new surplus balance is %d", peer, price, newSurplusBalance)
err = a.store.Put(peerSurplusBalanceKey(peer), newSurplusBalance) err = a.store.Put(peerSurplusBalanceKey(peer), newSurplusBalance)
...@@ -349,22 +320,19 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error { ...@@ -349,22 +320,19 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error {
} }
// if surplus balance didn't cover full transaction, let's continue with leftover part as cost // if surplus balance didn't cover full transaction, let's continue with leftover part as cost
debitIncrease, err := subtractU64mI64(price, surplusBalance) debitIncrease := new(big.Int).Sub(new(big.Int).SetUint64(price), surplusBalance)
if err != nil {
return err
}
// conversion to uint64 is safe because we know the relationship between the values by now, but let's make a sanity check // conversion to uint64 is safe because we know the relationship between the values by now, but let's make a sanity check
if debitIncrease <= 0 { if debitIncrease.Cmp(big.NewInt(0)) <= 0 {
return fmt.Errorf("sanity check failed for partial debit after surplus balance drawn") return fmt.Errorf("sanity check failed for partial debit after surplus balance drawn")
} }
cost = uint64(debitIncrease) cost.Set(debitIncrease)
// if we still have something to debit, than have run out of surplus balance, // if we still have something to debit, than have run out of surplus balance,
// let's store 0 as surplus balance // let's store 0 as surplus balance
a.logger.Tracef("surplus debiting peer %v with value %d, new surplus balance is 0", peer, debitIncrease) a.logger.Tracef("surplus debiting peer %v with value %d, new surplus balance is 0", peer, debitIncrease)
err = a.store.Put(peerSurplusBalanceKey(peer), 0) err = a.store.Put(peerSurplusBalanceKey(peer), big.NewInt(0))
if err != nil { if err != nil {
return fmt.Errorf("failed to persist surplus balance: %w", err) return fmt.Errorf("failed to persist surplus balance: %w", err)
} }
...@@ -379,10 +347,7 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error { ...@@ -379,10 +347,7 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error {
} }
// Get nextBalance by safely increasing current balance with price // Get nextBalance by safely increasing current balance with price
nextBalance, err := addI64pU64(currentBalance, cost) nextBalance := new(big.Int).Add(currentBalance, cost)
if err != nil {
return err
}
a.logger.Tracef("debiting peer %v with price %d, new balance is %d", peer, price, nextBalance) a.logger.Tracef("debiting peer %v with price %d, new balance is %d", peer, price, nextBalance)
...@@ -394,7 +359,7 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error { ...@@ -394,7 +359,7 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error {
a.metrics.TotalDebitedAmount.Add(float64(price)) a.metrics.TotalDebitedAmount.Add(float64(price))
a.metrics.DebitEventsCount.Inc() a.metrics.DebitEventsCount.Inc()
if nextBalance >= int64(a.paymentThreshold+a.paymentTolerance) { if nextBalance.Cmp(new(big.Int).Add(a.paymentThreshold, a.paymentTolerance)) >= 0 {
// peer too much in debt // peer too much in debt
a.metrics.AccountingDisconnectsCount.Inc() a.metrics.AccountingDisconnectsCount.Inc()
return p2p.NewBlockPeerError(10000*time.Hour, ErrDisconnectThresholdExceeded) return p2p.NewBlockPeerError(10000*time.Hour, ErrDisconnectThresholdExceeded)
...@@ -404,61 +369,58 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error { ...@@ -404,61 +369,58 @@ func (a *Accounting) Debit(peer swarm.Address, price uint64) error {
} }
// Balance returns the current balance for the given peer. // Balance returns the current balance for the given peer.
func (a *Accounting) Balance(peer swarm.Address) (balance int64, err error) { func (a *Accounting) Balance(peer swarm.Address) (balance *big.Int, err error) {
err = a.store.Get(peerBalanceKey(peer), &balance) err = a.store.Get(peerBalanceKey(peer), &balance)
if err != nil { if err != nil {
if errors.Is(err, storage.ErrNotFound) { if errors.Is(err, storage.ErrNotFound) {
return 0, ErrPeerNoBalance return big.NewInt(0), ErrPeerNoBalance
} }
return 0, err return nil, err
} }
return balance, nil return balance, nil
} }
// SurplusBalance returns the current balance for the given peer. // SurplusBalance returns the current balance for the given peer.
func (a *Accounting) SurplusBalance(peer swarm.Address) (balance int64, err error) { func (a *Accounting) SurplusBalance(peer swarm.Address) (balance *big.Int, err error) {
err = a.store.Get(peerSurplusBalanceKey(peer), &balance) err = a.store.Get(peerSurplusBalanceKey(peer), &balance)
if err != nil { if err != nil {
if errors.Is(err, storage.ErrNotFound) { if errors.Is(err, storage.ErrNotFound) {
return 0, nil return big.NewInt(0), nil
} }
return 0, err return nil, err
} }
return balance, nil return balance, nil
} }
// CompensatedBalance returns balance decreased by surplus balance // CompensatedBalance returns balance decreased by surplus balance
func (a *Accounting) CompensatedBalance(peer swarm.Address) (compensated int64, err error) { func (a *Accounting) CompensatedBalance(peer swarm.Address) (compensated *big.Int, err error) {
surplus, err := a.SurplusBalance(peer) surplus, err := a.SurplusBalance(peer)
if err != nil { if err != nil {
return 0, err return nil, err
} }
if surplus < 0 { if surplus.Cmp(big.NewInt(0)) < 0 {
return 0, ErrInvalidValue return nil, ErrInvalidValue
} }
balance, err := a.Balance(peer) balance, err := a.Balance(peer)
if err != nil { if err != nil {
if !errors.Is(err, ErrPeerNoBalance) { if !errors.Is(err, ErrPeerNoBalance) {
return 0, err return nil, err
} }
} }
// if surplus is 0 and peer has no balance, propagate ErrPeerNoBalance // if surplus is 0 and peer has no balance, propagate ErrPeerNoBalance
if surplus == 0 && errors.Is(err, ErrPeerNoBalance) { if surplus.Cmp(big.NewInt(0)) == 0 && errors.Is(err, ErrPeerNoBalance) {
return 0, err return nil, err
} }
// Compensated balance is balance decreased by surplus balance // Compensated balance is balance decreased by surplus balance
compensated, err = subtractI64mU64(balance, uint64(surplus)) compensated = new(big.Int).Sub(balance, surplus)
if err != nil {
return 0, err
}
return compensated, nil return compensated, nil
} }
...@@ -482,7 +444,7 @@ func (a *Accounting) getAccountingPeer(peer swarm.Address) (*accountingPeer, err ...@@ -482,7 +444,7 @@ func (a *Accounting) getAccountingPeer(peer swarm.Address) (*accountingPeer, err
peerData, ok := a.accountingPeers[peer.String()] peerData, ok := a.accountingPeers[peer.String()]
if !ok { if !ok {
peerData = &accountingPeer{ peerData = &accountingPeer{
reservedBalance: 0, reservedBalance: big.NewInt(0),
// initially assume the peer has the same threshold as us // initially assume the peer has the same threshold as us
paymentThreshold: a.paymentThreshold, paymentThreshold: a.paymentThreshold,
} }
...@@ -493,8 +455,8 @@ func (a *Accounting) getAccountingPeer(peer swarm.Address) (*accountingPeer, err ...@@ -493,8 +455,8 @@ func (a *Accounting) getAccountingPeer(peer swarm.Address) (*accountingPeer, err
} }
// Balances gets balances for all peers from store. // Balances gets balances for all peers from store.
func (a *Accounting) Balances() (map[string]int64, error) { func (a *Accounting) Balances() (map[string]*big.Int, error) {
s := make(map[string]int64) s := make(map[string]*big.Int)
err := a.store.Iterate(balancesPrefix, func(key, val []byte) (stop bool, err error) { err := a.store.Iterate(balancesPrefix, func(key, val []byte) (stop bool, err error) {
addr, err := balanceKeyPeer(key) addr, err := balanceKeyPeer(key)
...@@ -503,7 +465,7 @@ func (a *Accounting) Balances() (map[string]int64, error) { ...@@ -503,7 +465,7 @@ func (a *Accounting) Balances() (map[string]int64, error) {
} }
if _, ok := s[addr.String()]; !ok { if _, ok := s[addr.String()]; !ok {
var storevalue int64 var storevalue *big.Int
err = a.store.Get(peerBalanceKey(addr), &storevalue) err = a.store.Get(peerBalanceKey(addr), &storevalue)
if err != nil { if err != nil {
return false, fmt.Errorf("get peer %s balance: %v", addr.String(), err) return false, fmt.Errorf("get peer %s balance: %v", addr.String(), err)
...@@ -523,8 +485,8 @@ func (a *Accounting) Balances() (map[string]int64, error) { ...@@ -523,8 +485,8 @@ func (a *Accounting) Balances() (map[string]int64, error) {
} }
// Balances gets balances for all peers from store. // Balances gets balances for all peers from store.
func (a *Accounting) CompensatedBalances() (map[string]int64, error) { func (a *Accounting) CompensatedBalances() (map[string]*big.Int, error) {
s := make(map[string]int64) s := make(map[string]*big.Int)
err := a.store.Iterate(balancesPrefix, func(key, val []byte) (stop bool, err error) { err := a.store.Iterate(balancesPrefix, func(key, val []byte) (stop bool, err error) {
addr, err := balanceKeyPeer(key) addr, err := balanceKeyPeer(key)
...@@ -605,7 +567,7 @@ func surplusBalanceKeyPeer(key []byte) (swarm.Address, error) { ...@@ -605,7 +567,7 @@ func surplusBalanceKeyPeer(key []byte) (swarm.Address, error) {
} }
// NotifyPayment is called by Settlement when we receive a payment. // NotifyPayment is called by Settlement when we receive a payment.
func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error { func (a *Accounting) NotifyPayment(peer swarm.Address, amount *big.Int) error {
accountingPeer, err := a.getAccountingPeer(peer) accountingPeer, err := a.getAccountingPeer(peer)
if err != nil { if err != nil {
return err return err
...@@ -622,15 +584,12 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error { ...@@ -622,15 +584,12 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error {
} }
// if balance is already negative or zero, we credit full amount received to surplus balance and terminate early // if balance is already negative or zero, we credit full amount received to surplus balance and terminate early
if currentBalance <= 0 { if currentBalance.Cmp(big.NewInt(0)) <= 0 {
surplus, err := a.SurplusBalance(peer) surplus, err := a.SurplusBalance(peer)
if err != nil { if err != nil {
return fmt.Errorf("failed to get surplus balance: %w", err) return fmt.Errorf("failed to get surplus balance: %w", err)
} }
increasedSurplus, err := addI64pU64(surplus, amount) increasedSurplus := new(big.Int).Add(surplus, amount)
if err != nil {
return err
}
a.logger.Tracef("surplus crediting peer %v with amount %d due to payment, new surplus balance is %d", peer, amount, increasedSurplus) a.logger.Tracef("surplus crediting peer %v with amount %d due to payment, new surplus balance is %d", peer, amount, increasedSurplus)
...@@ -643,17 +602,14 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error { ...@@ -643,17 +602,14 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error {
} }
// if current balance is positive, let's make a partial credit to // if current balance is positive, let's make a partial credit to
newBalance, err := subtractI64mU64(currentBalance, amount) newBalance := new(big.Int).Sub(currentBalance, amount)
if err != nil {
return err
}
// Don't allow a payment to put us into debt // Don't allow a payment to put us into debt
// This is to prevent another node tricking us into settling by settling // This is to prevent another node tricking us into settling by settling
// first (e.g. send a bouncing cheque to trigger an honest cheque in swap). // first (e.g. send a bouncing cheque to trigger an honest cheque in swap).
nextBalance := newBalance nextBalance := newBalance
if newBalance < 0 { if newBalance.Cmp(big.NewInt(0)) < 0 {
nextBalance = 0 nextBalance = big.NewInt(0)
} }
a.logger.Tracef("crediting peer %v with amount %d due to payment, new balance is %d", peer, amount, nextBalance) a.logger.Tracef("crediting peer %v with amount %d due to payment, new balance is %d", peer, amount, nextBalance)
...@@ -666,20 +622,14 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error { ...@@ -666,20 +622,14 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error {
// If payment would have put us into debt, rather, let's add to surplusBalance, // If payment would have put us into debt, rather, let's add to surplusBalance,
// so as that an oversettlement attempt creates balance for future forwarding services // so as that an oversettlement attempt creates balance for future forwarding services
// charges to be deducted of // charges to be deducted of
if newBalance < 0 { if newBalance.Cmp(big.NewInt(0)) < 0 {
surplusGrowth, err := subtractU64mI64(amount, currentBalance) surplusGrowth := new(big.Int).Sub(amount, currentBalance)
if err != nil {
return err
}
surplus, err := a.SurplusBalance(peer) surplus, err := a.SurplusBalance(peer)
if err != nil { if err != nil {
return fmt.Errorf("failed to get surplus balance: %w", err) return fmt.Errorf("failed to get surplus balance: %w", err)
} }
increasedSurplus := surplus + surplusGrowth increasedSurplus := new(big.Int).Add(surplus, surplusGrowth)
if increasedSurplus < surplus {
return ErrOverflow
}
a.logger.Tracef("surplus crediting peer %v with amount %d due to payment, new surplus balance is %d", peer, surplusGrowth, increasedSurplus) a.logger.Tracef("surplus crediting peer %v with amount %d due to payment, new surplus balance is %d", peer, surplusGrowth, increasedSurplus)
...@@ -694,7 +644,7 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error { ...@@ -694,7 +644,7 @@ func (a *Accounting) NotifyPayment(peer swarm.Address, amount uint64) error {
// AsyncNotifyPayment calls notify payment in a go routine. // AsyncNotifyPayment calls notify payment in a go routine.
// This is needed when accounting needs to be notified but the accounting lock is already held. // This is needed when accounting needs to be notified but the accounting lock is already held.
func (a *Accounting) AsyncNotifyPayment(peer swarm.Address, amount uint64) error { func (a *Accounting) AsyncNotifyPayment(peer swarm.Address, amount *big.Int) error {
go func() { go func() {
err := a.NotifyPayment(peer, amount) err := a.NotifyPayment(peer, amount)
if err != nil { if err != nil {
...@@ -704,67 +654,8 @@ func (a *Accounting) AsyncNotifyPayment(peer swarm.Address, amount uint64) error ...@@ -704,67 +654,8 @@ func (a *Accounting) AsyncNotifyPayment(peer swarm.Address, amount uint64) error
return nil return nil
} }
// subtractI64mU64 is a helper function for safe subtraction of Int64 - Uint64
// It checks for
// - overflow safety in conversion of uint64 to int64
// - safety of the arithmetic
// - whether ( -1 * result ) is still Int64, as MinInt64 in absolute sense is 1 larger than MaxInt64
// If result is MinInt64, we also return overflow error, for two reasons:
// - in some cases we are going to use -1 * result in the following operations, which is secured by this check
// - we also do not want to possibly store this value as balance, even if ( -1 * result ) is not used immediately afterwards, because it could
// disable settleing for this amount as the value would create overflow
func subtractI64mU64(base int64, subtracted uint64) (result int64, err error) {
if subtracted > math.MaxInt64 {
return 0, ErrOverflow
}
result = base - int64(subtracted)
if result > base {
return 0, ErrOverflow
}
if result == math.MinInt64 {
return 0, ErrOverflow
}
return result, nil
}
func subtractU64mI64(base uint64, subtracted int64) (result int64, err error) {
if base > math.MaxInt64 {
return 0, ErrOverflow
}
// base is positive, overflow can happen by subtracting negative number
result = int64(base) - subtracted
if subtracted < 0 {
if result < int64(base) {
return 0, ErrOverflow
}
}
return result, nil
}
// addI64pU64 is a helper function for safe addition of Int64 + Uint64
// It checks for
// - overflow safety in conversion of uint64 to int64
// - safety of the arithmetic
func addI64pU64(a int64, b uint64) (result int64, err error) {
if b > math.MaxInt64 {
return 0, ErrOverflow
}
result = a + int64(b)
if result < a {
return 0, ErrOverflow
}
return result, nil
}
// NotifyPaymentThreshold should be called to notify accounting of changes in the payment threshold // NotifyPaymentThreshold should be called to notify accounting of changes in the payment threshold
func (a *Accounting) NotifyPaymentThreshold(peer swarm.Address, paymentThreshold uint64) error { func (a *Accounting) NotifyPaymentThreshold(peer swarm.Address, paymentThreshold *big.Int) error {
accountingPeer, err := a.getAccountingPeer(peer) accountingPeer, err := a.getAccountingPeer(peer)
if err != nil { if err != nil {
return err return err
...@@ -773,6 +664,6 @@ func (a *Accounting) NotifyPaymentThreshold(peer swarm.Address, paymentThreshold ...@@ -773,6 +664,6 @@ func (a *Accounting) NotifyPaymentThreshold(peer swarm.Address, paymentThreshold
accountingPeer.lock.Lock() accountingPeer.lock.Lock()
defer accountingPeer.lock.Unlock() defer accountingPeer.lock.Unlock()
accountingPeer.paymentThreshold = paymentThreshold accountingPeer.paymentThreshold.Set(paymentThreshold)
return nil return nil
} }
...@@ -8,22 +8,25 @@ import ( ...@@ -8,22 +8,25 @@ import (
"context" "context"
"errors" "errors"
"io/ioutil" "io/ioutil"
"math" "math/big"
"testing" "testing"
"github.com/ethersphere/bee/pkg/accounting" "github.com/ethersphere/bee/pkg/accounting"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p" "github.com/ethersphere/bee/pkg/p2p"
mockSettlement "github.com/ethersphere/bee/pkg/settlement/pseudosettle/mock" mockSettlement "github.com/ethersphere/bee/pkg/settlement/swap/mock"
"github.com/ethersphere/bee/pkg/statestore/mock" "github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
) )
const ( const (
testPaymentThreshold = 10000 testPrice = uint64(10)
testPaymentThresholdLarge = math.MaxInt64 - 1 )
testPaymentTolerance = 1000
testPrice = uint64(10) var (
testPaymentTolerance = big.NewInt(1000)
testPaymentEarly = big.NewInt(1000)
testPaymentThreshold = big.NewInt(10000)
) )
// booking represents an accounting action and the expected result afterwards // booking represents an accounting action and the expected result afterwards
...@@ -40,7 +43,7 @@ func TestAccountingAddBalance(t *testing.T) { ...@@ -40,7 +43,7 @@ func TestAccountingAddBalance(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, nil, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -86,7 +89,7 @@ func TestAccountingAddBalance(t *testing.T) { ...@@ -86,7 +89,7 @@ func TestAccountingAddBalance(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != booking.expectedBalance { if balance.Int64() != booking.expectedBalance {
t.Fatalf("balance for peer %v not as expected after booking %d. got %d, wanted %d", booking.peer.String(), i, balance, booking.expectedBalance) t.Fatalf("balance for peer %v not as expected after booking %d. got %d, wanted %d", booking.peer.String(), i, balance, booking.expectedBalance)
} }
} }
...@@ -101,7 +104,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) { ...@@ -101,7 +104,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, nil, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -128,7 +131,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) { ...@@ -128,7 +131,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
acc, err = accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, nil, nil) acc, err = accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -138,7 +141,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) { ...@@ -138,7 +141,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if peer1Balance != int64(peer1DebitAmount) { if peer1Balance.Uint64() != peer1DebitAmount {
t.Fatalf("peer1Balance not loaded correctly. got %d, wanted %d", peer1Balance, peer1DebitAmount) t.Fatalf("peer1Balance not loaded correctly. got %d, wanted %d", peer1Balance, peer1DebitAmount)
} }
...@@ -147,7 +150,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) { ...@@ -147,7 +150,7 @@ func TestAccountingAdd_persistentBalances(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if peer2Balance != -int64(peer2CreditAmount) { if peer2Balance.Int64() != -int64(peer2CreditAmount) {
t.Fatalf("peer2Balance not loaded correctly. got %d, wanted %d", peer2Balance, -int64(peer2CreditAmount)) t.Fatalf("peer2Balance not loaded correctly. got %d, wanted %d", peer2Balance, -int64(peer2CreditAmount))
} }
} }
...@@ -159,7 +162,7 @@ func TestAccountingReserve(t *testing.T) { ...@@ -159,7 +162,7 @@ func TestAccountingReserve(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, nil, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -170,7 +173,7 @@ func TestAccountingReserve(t *testing.T) { ...@@ -170,7 +173,7 @@ func TestAccountingReserve(t *testing.T) {
} }
// it should allow to cross the threshold one time // it should allow to cross the threshold one time
err = acc.Reserve(context.Background(), peer1Addr, testPaymentThreshold+1) err = acc.Reserve(context.Background(), peer1Addr, testPaymentThreshold.Uint64()+1)
if err == nil { if err == nil {
t.Fatal("expected error from reserve") t.Fatal("expected error from reserve")
} }
...@@ -180,225 +183,6 @@ func TestAccountingReserve(t *testing.T) { ...@@ -180,225 +183,6 @@ func TestAccountingReserve(t *testing.T) {
} }
} }
func TestAccountingOverflowReserve(t *testing.T) {
logger := logging.New(ioutil.Discard, 0)
store := mock.NewStateStore()
defer store.Close()
settlement := mockSettlement.NewSettlement()
acc, err := accounting.NewAccounting(testPaymentThresholdLarge, 0, 0, logger, store, settlement, nil)
if err != nil {
t.Fatal(err)
}
peer1Addr, err := swarm.ParseHexAddress("00112233")
if err != nil {
t.Fatal(err)
}
err = acc.Reserve(context.Background(), peer1Addr, testPaymentThresholdLarge)
if err != nil {
t.Fatal(err)
}
err = acc.Reserve(context.Background(), peer1Addr, math.MaxInt64)
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Reserve, got %v", err)
}
acc.Release(peer1Addr, testPaymentThresholdLarge)
// Try crediting near maximal value for peer
err = acc.Credit(peer1Addr, math.MaxInt64)
if err != nil {
t.Fatal(err)
}
// Try reserving further value, should overflow
err = acc.Reserve(context.Background(), peer1Addr, 1)
// If we had other error, assert fail
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Reserve, got %v", err)
}
}
func TestAccountingOverflowSurplusBalance(t *testing.T) {
logger := logging.New(ioutil.Discard, 0)
store := mock.NewStateStore()
defer store.Close()
settlement := mockSettlement.NewSettlement()
acc, err := accounting.NewAccounting(testPaymentThresholdLarge, 0, 0, logger, store, settlement, nil)
if err != nil {
t.Fatal(err)
}
peer1Addr, err := swarm.ParseHexAddress("00112233")
if err != nil {
t.Fatal(err)
}
// Try Debiting a large amount to peer so balance is large positive
err = acc.Debit(peer1Addr, testPaymentThresholdLarge-1)
if err != nil {
t.Fatal(err)
}
// Notify of incoming payment from same peer, so balance goes to 0 with surplusbalance 2
err = acc.NotifyPayment(peer1Addr, math.MaxInt64)
if err != nil {
t.Fatal("Unexpected overflow from NotifyPayment")
}
// sanity check surplus balance
val, err := acc.SurplusBalance(peer1Addr)
if err != nil {
t.Fatal("Error checking Surplusbalance")
}
if val != 2 {
t.Fatal("Not expected surplus balance")
}
// sanity check balance
val, err = acc.Balance(peer1Addr)
if err != nil {
t.Fatal("Error checking Balance")
}
if val != 0 {
t.Fatal("Unexpected balance")
}
// Notify of incoming payment from same peer, further decreasing balance, this should overflow
err = acc.NotifyPayment(peer1Addr, math.MaxInt64)
if err == nil {
t.Fatal("Expected overflow from NotifyPayment")
}
// If we had other error, assert fail
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatal("Expected overflow error from NotifyPayment")
}
}
func TestAccountingOverflowNotifyPayment(t *testing.T) {
logger := logging.New(ioutil.Discard, 0)
store := mock.NewStateStore()
defer store.Close()
settlement := mockSettlement.NewSettlement()
acc, err := accounting.NewAccounting(testPaymentThresholdLarge, 0, 0, logger, store, settlement, nil)
if err != nil {
t.Fatal(err)
}
peer1Addr, err := swarm.ParseHexAddress("00112233")
if err != nil {
t.Fatal(err)
}
// Try Crediting a large amount to peer so balance is negative
err = acc.Credit(peer1Addr, math.MaxInt64)
if err != nil {
t.Fatal(err)
}
// NotifyPayment for peer should now fill the surplus balance
err = acc.NotifyPayment(peer1Addr, math.MaxInt64)
if err != nil {
t.Fatalf("Expected no error but got one: %v", err)
}
// Notify of incoming payment from same peer, further increasing the surplus balance into an overflow
err = acc.NotifyPayment(peer1Addr, 1)
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Debit, got %v", err)
}
}
func TestAccountingOverflowDebit(t *testing.T) {
logger := logging.New(ioutil.Discard, 0)
store := mock.NewStateStore()
defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThresholdLarge, 0, 0, logger, store, nil, nil)
if err != nil {
t.Fatal(err)
}
peer1Addr, err := swarm.ParseHexAddress("00112233")
if err != nil {
t.Fatal(err)
}
// Try increasing peer debit with near maximal value
err = acc.Debit(peer1Addr, math.MaxInt64-2)
if err != nil {
t.Fatal(err)
}
// Try further increasing peer debit with near maximal value, this should fail
err = acc.Debit(peer1Addr, math.MaxInt64-2)
if err == nil {
t.Fatal("Expected error from overflow Debit")
}
// If we had other error, assert fail
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Credit, got %v", err)
}
// Try further increasing peer debit with near maximal value, this should fail
err = acc.Debit(peer1Addr, math.MaxInt64)
if err == nil {
t.Fatal("Expected error from overflow Debit")
}
// If we had other error, assert fail
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Debit, got %v", err)
}
}
func TestAccountingOverflowCredit(t *testing.T) {
logger := logging.New(ioutil.Discard, 0)
store := mock.NewStateStore()
defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThresholdLarge, 0, 0, logger, store, nil, nil)
if err != nil {
t.Fatal(err)
}
peer1Addr, err := swarm.ParseHexAddress("00112233")
if err != nil {
t.Fatal(err)
}
// Try increasing peer credit with near maximal value
err = acc.Credit(peer1Addr, math.MaxInt64-2)
if err != nil {
t.Fatal(err)
}
// Try increasing with a further near maximal value, this must overflow
err = acc.Credit(peer1Addr, math.MaxInt64-2)
if err == nil {
t.Fatal("Expected error from overflow Credit")
}
// Try increasing with a small amount, which should also overflow
err = acc.Credit(peer1Addr, 3)
if err == nil {
t.Fatal("Expected error from overflow Credit")
}
// If we had other error, assert fail
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Credit, got %v", err)
}
// Try increasing with maximal value
err = acc.Credit(peer1Addr, math.MaxInt64)
if err == nil {
t.Fatal("Expected error from overflow Credit")
}
// If we had other error, assert fail
if !errors.Is(err, accounting.ErrOverflow) {
t.Fatalf("expected overflow error from Credit, got %v", err)
}
}
// TestAccountingDisconnect tests that exceeding the disconnect threshold with Debit returns a p2p.DisconnectError // TestAccountingDisconnect tests that exceeding the disconnect threshold with Debit returns a p2p.DisconnectError
func TestAccountingDisconnect(t *testing.T) { func TestAccountingDisconnect(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
...@@ -406,7 +190,7 @@ func TestAccountingDisconnect(t *testing.T) { ...@@ -406,7 +190,7 @@ func TestAccountingDisconnect(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, nil, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -417,7 +201,7 @@ func TestAccountingDisconnect(t *testing.T) { ...@@ -417,7 +201,7 @@ func TestAccountingDisconnect(t *testing.T) {
} }
// put the peer 1 unit away from disconnect // put the peer 1 unit away from disconnect
err = acc.Debit(peer1Addr, testPaymentThreshold+testPaymentTolerance-1) err = acc.Debit(peer1Addr, testPaymentThreshold.Uint64()+testPaymentTolerance.Uint64()-1)
if err != nil { if err != nil {
t.Fatal("expected no error while still within tolerance") t.Fatal("expected no error while still within tolerance")
} }
...@@ -441,9 +225,9 @@ func TestAccountingCallSettlement(t *testing.T) { ...@@ -441,9 +225,9 @@ func TestAccountingCallSettlement(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
settlement := mockSettlement.NewSettlement() settlement := mockSettlement.New()
acc, err := accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, settlement, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, settlement, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -453,18 +237,18 @@ func TestAccountingCallSettlement(t *testing.T) { ...@@ -453,18 +237,18 @@ func TestAccountingCallSettlement(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = acc.Reserve(context.Background(), peer1Addr, testPaymentThreshold) err = acc.Reserve(context.Background(), peer1Addr, testPaymentThreshold.Uint64())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Credit until payment treshold // Credit until payment treshold
err = acc.Credit(peer1Addr, testPaymentThreshold) err = acc.Credit(peer1Addr, testPaymentThreshold.Uint64())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
acc.Release(peer1Addr, testPaymentThreshold) acc.Release(peer1Addr, testPaymentThreshold.Uint64())
// try another request // try another request
err = acc.Reserve(context.Background(), peer1Addr, 1) err = acc.Reserve(context.Background(), peer1Addr, 1)
...@@ -479,7 +263,7 @@ func TestAccountingCallSettlement(t *testing.T) { ...@@ -479,7 +263,7 @@ func TestAccountingCallSettlement(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if totalSent != testPaymentThreshold { if totalSent.Cmp(testPaymentThreshold) != 0 {
t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, testPaymentThreshold) t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, testPaymentThreshold)
} }
...@@ -487,7 +271,7 @@ func TestAccountingCallSettlement(t *testing.T) { ...@@ -487,7 +271,7 @@ func TestAccountingCallSettlement(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if balance != 0 { if balance.Int64() != 0 {
t.Fatalf("expected balance to be reset. got %d", balance) t.Fatalf("expected balance to be reset. got %d", balance)
} }
...@@ -498,7 +282,7 @@ func TestAccountingCallSettlement(t *testing.T) { ...@@ -498,7 +282,7 @@ func TestAccountingCallSettlement(t *testing.T) {
} }
// Credit until the expected debt exceeeds payment threshold // Credit until the expected debt exceeeds payment threshold
expectedAmount := uint64(testPaymentThreshold - 100) expectedAmount := testPaymentThreshold.Uint64() - 100
err = acc.Reserve(context.Background(), peer1Addr, expectedAmount) err = acc.Reserve(context.Background(), peer1Addr, expectedAmount)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -524,8 +308,8 @@ func TestAccountingCallSettlement(t *testing.T) { ...@@ -524,8 +308,8 @@ func TestAccountingCallSettlement(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if totalSent != expectedAmount+testPaymentThreshold { if totalSent.Cmp(new(big.Int).Add(new(big.Int).SetUint64(expectedAmount), testPaymentThreshold)) != 0 {
t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, expectedAmount+testPaymentThreshold) t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, new(big.Int).Add(new(big.Int).SetUint64(expectedAmount), testPaymentThreshold))
} }
acc.Release(peer1Addr, 100) acc.Release(peer1Addr, 100)
...@@ -538,9 +322,9 @@ func TestAccountingCallSettlementEarly(t *testing.T) { ...@@ -538,9 +322,9 @@ func TestAccountingCallSettlementEarly(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
settlement := mockSettlement.NewSettlement() settlement := mockSettlement.New()
debt := uint64(500) debt := uint64(500)
earlyPayment := uint64(1000) earlyPayment := big.NewInt(1000)
acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, earlyPayment, logger, store, settlement, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, earlyPayment, logger, store, settlement, nil)
if err != nil { if err != nil {
...@@ -557,7 +341,7 @@ func TestAccountingCallSettlementEarly(t *testing.T) { ...@@ -557,7 +341,7 @@ func TestAccountingCallSettlementEarly(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
payment := testPaymentThreshold - earlyPayment payment := testPaymentThreshold.Uint64() - earlyPayment.Uint64()
err = acc.Reserve(context.Background(), peer1Addr, payment) err = acc.Reserve(context.Background(), peer1Addr, payment)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
...@@ -570,7 +354,7 @@ func TestAccountingCallSettlementEarly(t *testing.T) { ...@@ -570,7 +354,7 @@ func TestAccountingCallSettlementEarly(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if totalSent != debt { if totalSent.Cmp(new(big.Int).SetUint64(debt)) != 0 {
t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, testPaymentThreshold) t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, testPaymentThreshold)
} }
...@@ -578,7 +362,7 @@ func TestAccountingCallSettlementEarly(t *testing.T) { ...@@ -578,7 +362,7 @@ func TestAccountingCallSettlementEarly(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if balance != 0 { if balance.Int64() != 0 {
t.Fatalf("expected balance to be reset. got %d", balance) t.Fatalf("expected balance to be reset. got %d", balance)
} }
} }
...@@ -589,9 +373,9 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -589,9 +373,9 @@ func TestAccountingSurplusBalance(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
settlement := mockSettlement.NewSettlement() settlement := mockSettlement.New()
acc, err := accounting.NewAccounting(testPaymentThreshold, 0, 0, logger, store, settlement, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, big.NewInt(0), big.NewInt(0), logger, store, settlement, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -600,12 +384,12 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -600,12 +384,12 @@ func TestAccountingSurplusBalance(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// Try Debiting a large amount to peer so balance is large positive // Try Debiting a large amount to peer so balance is large positive
err = acc.Debit(peer1Addr, testPaymentThreshold-1) err = acc.Debit(peer1Addr, testPaymentThreshold.Uint64()-1)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Notify of incoming payment from same peer, so balance goes to 0 with surplusbalance 2 // Notify of incoming payment from same peer, so balance goes to 0 with surplusbalance 2
err = acc.NotifyPayment(peer1Addr, testPaymentThreshold+1) err = acc.NotifyPayment(peer1Addr, new(big.Int).Add(testPaymentThreshold, big.NewInt(1)))
if err != nil { if err != nil {
t.Fatal("Unexpected overflow from doable NotifyPayment") t.Fatal("Unexpected overflow from doable NotifyPayment")
} }
...@@ -614,7 +398,7 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -614,7 +398,7 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Surplusbalance") t.Fatal("Error checking Surplusbalance")
} }
if val != 2 { if val.Int64() != 2 {
t.Fatal("Not expected surplus balance") t.Fatal("Not expected surplus balance")
} }
//sanity check balance //sanity check balance
...@@ -622,7 +406,7 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -622,7 +406,7 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Balance") t.Fatal("Error checking Balance")
} }
if val != 0 { if val.Int64() != 0 {
t.Fatal("Not expected balance") t.Fatal("Not expected balance")
} }
// Notify of incoming payment from same peer, so balance goes to 0 with surplusbalance 10002 (testpaymentthreshold+2) // Notify of incoming payment from same peer, so balance goes to 0 with surplusbalance 10002 (testpaymentthreshold+2)
...@@ -635,7 +419,7 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -635,7 +419,7 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Surplusbalance") t.Fatal("Error checking Surplusbalance")
} }
if val != testPaymentThreshold+2 { if val.Int64() != testPaymentThreshold.Int64()+2 {
t.Fatal("Unexpected surplus balance") t.Fatal("Unexpected surplus balance")
} }
//sanity check balance //sanity check balance
...@@ -643,11 +427,11 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -643,11 +427,11 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Balance") t.Fatal("Error checking Balance")
} }
if val != 0 { if val.Int64() != 0 {
t.Fatal("Not expected balance, expected 0") t.Fatal("Not expected balance, expected 0")
} }
// Debit for same peer, so balance stays 0 with surplusbalance decreasing to 2 // Debit for same peer, so balance stays 0 with surplusbalance decreasing to 2
err = acc.Debit(peer1Addr, testPaymentThreshold) err = acc.Debit(peer1Addr, testPaymentThreshold.Uint64())
if err != nil { if err != nil {
t.Fatal("Unexpected error from Credit") t.Fatal("Unexpected error from Credit")
} }
...@@ -656,7 +440,7 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -656,7 +440,7 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Surplusbalance") t.Fatal("Error checking Surplusbalance")
} }
if val != 2 { if val.Int64() != 2 {
t.Fatal("Unexpected surplus balance") t.Fatal("Unexpected surplus balance")
} }
//sanity check balance //sanity check balance
...@@ -664,11 +448,11 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -664,11 +448,11 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Balance") t.Fatal("Error checking Balance")
} }
if val != 0 { if val.Int64() != 0 {
t.Fatal("Not expected balance, expected 0") t.Fatal("Not expected balance, expected 0")
} }
// Debit for same peer, so balance goes to 9998 (testpaymentthreshold - 2) with surplusbalance decreasing to 0 // Debit for same peer, so balance goes to 9998 (testpaymentthreshold - 2) with surplusbalance decreasing to 0
err = acc.Debit(peer1Addr, testPaymentThreshold) err = acc.Debit(peer1Addr, testPaymentThreshold.Uint64())
if err != nil { if err != nil {
t.Fatal("Unexpected error from NotifyPayment") t.Fatal("Unexpected error from NotifyPayment")
} }
...@@ -677,7 +461,7 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -677,7 +461,7 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Surplusbalance") t.Fatal("Error checking Surplusbalance")
} }
if val != 0 { if val.Int64() != 0 {
t.Fatal("Unexpected surplus balance") t.Fatal("Unexpected surplus balance")
} }
//sanity check balance //sanity check balance
...@@ -685,7 +469,7 @@ func TestAccountingSurplusBalance(t *testing.T) { ...@@ -685,7 +469,7 @@ func TestAccountingSurplusBalance(t *testing.T) {
if err != nil { if err != nil {
t.Fatal("Error checking Balance") t.Fatal("Error checking Balance")
} }
if val != testPaymentThreshold-2 { if val.Int64() != testPaymentThreshold.Int64()-2 {
t.Fatal("Not expected balance, expected 0") t.Fatal("Not expected balance, expected 0")
} }
} }
...@@ -697,7 +481,7 @@ func TestAccountingNotifyPayment(t *testing.T) { ...@@ -697,7 +481,7 @@ func TestAccountingNotifyPayment(t *testing.T) {
store := mock.NewStateStore() store := mock.NewStateStore()
defer store.Close() defer store.Close()
acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, 1000, logger, store, nil, nil) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -708,12 +492,12 @@ func TestAccountingNotifyPayment(t *testing.T) { ...@@ -708,12 +492,12 @@ func TestAccountingNotifyPayment(t *testing.T) {
} }
debtAmount := uint64(100) debtAmount := uint64(100)
err = acc.Debit(peer1Addr, debtAmount+testPaymentTolerance) err = acc.Debit(peer1Addr, debtAmount+testPaymentTolerance.Uint64())
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
err = acc.NotifyPayment(peer1Addr, debtAmount+testPaymentTolerance) err = acc.NotifyPayment(peer1Addr, new(big.Int).SetUint64(debtAmount+testPaymentTolerance.Uint64()))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -723,7 +507,7 @@ func TestAccountingNotifyPayment(t *testing.T) { ...@@ -723,7 +507,7 @@ func TestAccountingNotifyPayment(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
err = acc.NotifyPayment(peer1Addr, debtAmount+testPaymentTolerance+1) err = acc.NotifyPayment(peer1Addr, new(big.Int).SetUint64(debtAmount+testPaymentTolerance.Uint64()+1))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -732,10 +516,10 @@ func TestAccountingNotifyPayment(t *testing.T) { ...@@ -732,10 +516,10 @@ func TestAccountingNotifyPayment(t *testing.T) {
type pricingMock struct { type pricingMock struct {
called bool called bool
peer swarm.Address peer swarm.Address
paymentThreshold uint64 paymentThreshold *big.Int
} }
func (p *pricingMock) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Address, paymentThreshold uint64) error { func (p *pricingMock) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Address, paymentThreshold *big.Int) error {
p.called = true p.called = true
p.peer = peer p.peer = peer
p.paymentThreshold = paymentThreshold p.paymentThreshold = paymentThreshold
...@@ -750,7 +534,7 @@ func TestAccountingConnected(t *testing.T) { ...@@ -750,7 +534,7 @@ func TestAccountingConnected(t *testing.T) {
pricing := &pricingMock{} pricing := &pricingMock{}
_, err := accounting.NewAccounting(testPaymentThreshold, 1000, 1000, logger, store, nil, pricing) _, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, testPaymentEarly, logger, store, nil, pricing)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -785,9 +569,9 @@ func TestAccountingNotifyPaymentThreshold(t *testing.T) { ...@@ -785,9 +569,9 @@ func TestAccountingNotifyPaymentThreshold(t *testing.T) {
defer store.Close() defer store.Close()
pricing := &pricingMock{} pricing := &pricingMock{}
settlement := mockSettlement.NewSettlement() settlement := mockSettlement.New()
acc, err := accounting.NewAccounting(testPaymentThreshold, 1000, 0, logger, store, settlement, pricing) acc, err := accounting.NewAccounting(testPaymentThreshold, testPaymentTolerance, big.NewInt(0), logger, store, settlement, pricing)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -800,7 +584,7 @@ func TestAccountingNotifyPaymentThreshold(t *testing.T) { ...@@ -800,7 +584,7 @@ func TestAccountingNotifyPaymentThreshold(t *testing.T) {
debt := uint64(50) debt := uint64(50)
lowerThreshold := uint64(100) lowerThreshold := uint64(100)
err = acc.NotifyPaymentThreshold(peer1Addr, lowerThreshold) err = acc.NotifyPaymentThreshold(peer1Addr, new(big.Int).SetUint64(lowerThreshold))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -820,7 +604,7 @@ func TestAccountingNotifyPaymentThreshold(t *testing.T) { ...@@ -820,7 +604,7 @@ func TestAccountingNotifyPaymentThreshold(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if totalSent != debt { if totalSent.Cmp(new(big.Int).SetUint64(debt)) != 0 {
t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, debt) t.Fatalf("paid wrong amount. got %d wanted %d", totalSent, debt)
} }
} }
...@@ -6,6 +6,7 @@ package mock ...@@ -6,6 +6,7 @@ package mock
import ( import (
"context" "context"
"math/big"
"sync" "sync"
"github.com/ethersphere/bee/pkg/accounting" "github.com/ethersphere/bee/pkg/accounting"
...@@ -15,17 +16,17 @@ import ( ...@@ -15,17 +16,17 @@ import (
// Service is the mock Accounting service. // Service is the mock Accounting service.
type Service struct { type Service struct {
lock sync.Mutex lock sync.Mutex
balances map[string]int64 balances map[string]*big.Int
reserveFunc func(ctx context.Context, peer swarm.Address, price uint64) error reserveFunc func(ctx context.Context, peer swarm.Address, price uint64) error
releaseFunc func(peer swarm.Address, price uint64) releaseFunc func(peer swarm.Address, price uint64)
creditFunc func(peer swarm.Address, price uint64) error creditFunc func(peer swarm.Address, price uint64) error
debitFunc func(peer swarm.Address, price uint64) error debitFunc func(peer swarm.Address, price uint64) error
balanceFunc func(swarm.Address) (int64, error) balanceFunc func(swarm.Address) (*big.Int, error)
balancesFunc func() (map[string]int64, error) balancesFunc func() (map[string]*big.Int, error)
compensatedBalanceFunc func(swarm.Address) (int64, error) compensatedBalanceFunc func(swarm.Address) (*big.Int, error)
compensatedBalancesFunc func() (map[string]int64, error) compensatedBalancesFunc func() (map[string]*big.Int, error)
balanceSurplusFunc func(swarm.Address) (int64, error) balanceSurplusFunc func(swarm.Address) (*big.Int, error)
} }
// WithReserveFunc sets the mock Reserve function // WithReserveFunc sets the mock Reserve function
...@@ -57,35 +58,35 @@ func WithDebitFunc(f func(peer swarm.Address, price uint64) error) Option { ...@@ -57,35 +58,35 @@ func WithDebitFunc(f func(peer swarm.Address, price uint64) error) Option {
} }
// WithBalanceFunc sets the mock Balance function // WithBalanceFunc sets the mock Balance function
func WithBalanceFunc(f func(swarm.Address) (int64, error)) Option { func WithBalanceFunc(f func(swarm.Address) (*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.balanceFunc = f s.balanceFunc = f
}) })
} }
// WithBalancesFunc sets the mock Balances function // WithBalancesFunc sets the mock Balances function
func WithBalancesFunc(f func() (map[string]int64, error)) Option { func WithBalancesFunc(f func() (map[string]*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.balancesFunc = f s.balancesFunc = f
}) })
} }
// WithCompensatedBalanceFunc sets the mock Balance function // WithCompensatedBalanceFunc sets the mock Balance function
func WithCompensatedBalanceFunc(f func(swarm.Address) (int64, error)) Option { func WithCompensatedBalanceFunc(f func(swarm.Address) (*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.compensatedBalanceFunc = f s.compensatedBalanceFunc = f
}) })
} }
// WithCompensatedBalancesFunc sets the mock Balances function // WithCompensatedBalancesFunc sets the mock Balances function
func WithCompensatedBalancesFunc(f func() (map[string]int64, error)) Option { func WithCompensatedBalancesFunc(f func() (map[string]*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.compensatedBalancesFunc = f s.compensatedBalancesFunc = f
}) })
} }
// WithBalanceSurplusFunc sets the mock SurplusBalance function // WithBalanceSurplusFunc sets the mock SurplusBalance function
func WithBalanceSurplusFunc(f func(swarm.Address) (int64, error)) Option { func WithBalanceSurplusFunc(f func(swarm.Address) (*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.balanceSurplusFunc = f s.balanceSurplusFunc = f
}) })
...@@ -94,7 +95,7 @@ func WithBalanceSurplusFunc(f func(swarm.Address) (int64, error)) Option { ...@@ -94,7 +95,7 @@ func WithBalanceSurplusFunc(f func(swarm.Address) (int64, error)) Option {
// NewAccounting creates the mock accounting implementation // NewAccounting creates the mock accounting implementation
func NewAccounting(opts ...Option) accounting.Interface { func NewAccounting(opts ...Option) accounting.Interface {
mock := new(Service) mock := new(Service)
mock.balances = make(map[string]int64) mock.balances = make(map[string]*big.Int)
for _, o := range opts { for _, o := range opts {
o.apply(mock) o.apply(mock)
} }
...@@ -123,7 +124,12 @@ func (s *Service) Credit(peer swarm.Address, price uint64) error { ...@@ -123,7 +124,12 @@ func (s *Service) Credit(peer swarm.Address, price uint64) error {
} }
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
s.balances[peer.String()] -= int64(price)
if bal, ok := s.balances[peer.String()]; ok {
s.balances[peer.String()] = new(big.Int).Sub(bal, new(big.Int).SetUint64(price))
} else {
s.balances[peer.String()] = big.NewInt(-int64(price))
}
return nil return nil
} }
...@@ -134,22 +140,31 @@ func (s *Service) Debit(peer swarm.Address, price uint64) error { ...@@ -134,22 +140,31 @@ func (s *Service) Debit(peer swarm.Address, price uint64) error {
} }
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
s.balances[peer.String()] += int64(price)
if bal, ok := s.balances[peer.String()]; ok {
s.balances[peer.String()] = new(big.Int).Add(bal, new(big.Int).SetUint64(price))
} else {
s.balances[peer.String()] = new(big.Int).SetUint64(price)
}
return nil return nil
} }
// Balance is the mock function wrapper that calls the set implementation // Balance is the mock function wrapper that calls the set implementation
func (s *Service) Balance(peer swarm.Address) (int64, error) { func (s *Service) Balance(peer swarm.Address) (*big.Int, error) {
if s.balanceFunc != nil { if s.balanceFunc != nil {
return s.balanceFunc(peer) return s.balanceFunc(peer)
} }
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
return s.balances[peer.String()], nil if bal, ok := s.balances[peer.String()]; ok {
return bal, nil
} else {
return big.NewInt(0), nil
}
} }
// Balances is the mock function wrapper that calls the set implementation // Balances is the mock function wrapper that calls the set implementation
func (s *Service) Balances() (map[string]int64, error) { func (s *Service) Balances() (map[string]*big.Int, error) {
if s.balancesFunc != nil { if s.balancesFunc != nil {
return s.balancesFunc() return s.balancesFunc()
} }
...@@ -157,7 +172,7 @@ func (s *Service) Balances() (map[string]int64, error) { ...@@ -157,7 +172,7 @@ func (s *Service) Balances() (map[string]int64, error) {
} }
// CompensatedBalance is the mock function wrapper that calls the set implementation // CompensatedBalance is the mock function wrapper that calls the set implementation
func (s *Service) CompensatedBalance(peer swarm.Address) (int64, error) { func (s *Service) CompensatedBalance(peer swarm.Address) (*big.Int, error) {
if s.compensatedBalanceFunc != nil { if s.compensatedBalanceFunc != nil {
return s.compensatedBalanceFunc(peer) return s.compensatedBalanceFunc(peer)
} }
...@@ -167,7 +182,7 @@ func (s *Service) CompensatedBalance(peer swarm.Address) (int64, error) { ...@@ -167,7 +182,7 @@ func (s *Service) CompensatedBalance(peer swarm.Address) (int64, error) {
} }
// CompensatedBalances is the mock function wrapper that calls the set implementation // CompensatedBalances is the mock function wrapper that calls the set implementation
func (s *Service) CompensatedBalances() (map[string]int64, error) { func (s *Service) CompensatedBalances() (map[string]*big.Int, error) {
if s.compensatedBalancesFunc != nil { if s.compensatedBalancesFunc != nil {
return s.compensatedBalancesFunc() return s.compensatedBalancesFunc()
} }
...@@ -175,13 +190,13 @@ func (s *Service) CompensatedBalances() (map[string]int64, error) { ...@@ -175,13 +190,13 @@ func (s *Service) CompensatedBalances() (map[string]int64, error) {
} }
// //
func (s *Service) SurplusBalance(peer swarm.Address) (int64, error) { func (s *Service) SurplusBalance(peer swarm.Address) (*big.Int, error) {
if s.balanceFunc != nil { if s.balanceFunc != nil {
return s.balanceSurplusFunc(peer) return s.balanceSurplusFunc(peer)
} }
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
return 0, nil return big.NewInt(0), nil
} }
// Option is the option passed to the mock accounting service // Option is the option passed to the mock accounting service
......
...@@ -6,6 +6,7 @@ package debugapi ...@@ -6,6 +6,7 @@ package debugapi
import ( import (
"errors" "errors"
"math/big"
"net/http" "net/http"
"github.com/ethersphere/bee/pkg/accounting" "github.com/ethersphere/bee/pkg/accounting"
...@@ -22,8 +23,8 @@ var ( ...@@ -22,8 +23,8 @@ var (
) )
type balanceResponse struct { type balanceResponse struct {
Peer string `json:"peer"` Peer string `json:"peer"`
Balance int64 `json:"balance"` Balance *big.Int `json:"balance"`
} }
type balancesResponse struct { type balancesResponse struct {
......
...@@ -6,6 +6,7 @@ package debugapi_test ...@@ -6,6 +6,7 @@ package debugapi_test
import ( import (
"errors" "errors"
"math/big"
"net/http" "net/http"
"reflect" "reflect"
"testing" "testing"
...@@ -19,11 +20,11 @@ import ( ...@@ -19,11 +20,11 @@ import (
) )
func TestBalances(t *testing.T) { func TestBalances(t *testing.T) {
compensatedBalancesFunc := func() (ret map[string]int64, err error) { compensatedBalancesFunc := func() (ret map[string]*big.Int, err error) {
ret = make(map[string]int64) ret = make(map[string]*big.Int)
ret["DEAD"] = 1000000000000000000 ret["DEAD"] = big.NewInt(1000000000000000000)
ret["BEEF"] = -100000000000000000 ret["BEEF"] = big.NewInt(-100000000000000000)
ret["PARTY"] = 0 ret["PARTY"] = big.NewInt(0)
return ret, err return ret, err
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
...@@ -34,15 +35,15 @@ func TestBalances(t *testing.T) { ...@@ -34,15 +35,15 @@ func TestBalances(t *testing.T) {
[]debugapi.BalanceResponse{ []debugapi.BalanceResponse{
{ {
Peer: "DEAD", Peer: "DEAD",
Balance: 1000000000000000000, Balance: big.NewInt(1000000000000000000),
}, },
{ {
Peer: "BEEF", Peer: "BEEF",
Balance: -100000000000000000, Balance: big.NewInt(-100000000000000000),
}, },
{ {
Peer: "PARTY", Peer: "PARTY",
Balance: 0, Balance: big.NewInt(0),
}, },
}, },
} }
...@@ -61,7 +62,7 @@ func TestBalances(t *testing.T) { ...@@ -61,7 +62,7 @@ func TestBalances(t *testing.T) {
func TestBalancesError(t *testing.T) { func TestBalancesError(t *testing.T) {
wantErr := errors.New("ASDF") wantErr := errors.New("ASDF")
compensatedBalancesFunc := func() (ret map[string]int64, err error) { compensatedBalancesFunc := func() (ret map[string]*big.Int, err error) {
return nil, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
...@@ -78,8 +79,8 @@ func TestBalancesError(t *testing.T) { ...@@ -78,8 +79,8 @@ func TestBalancesError(t *testing.T) {
func TestBalancesPeers(t *testing.T) { func TestBalancesPeers(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
compensatedBalanceFunc := func(swarm.Address) (int64, error) { compensatedBalanceFunc := func(swarm.Address) (*big.Int, error) {
return 1000000000000000000, nil return big.NewInt(100000000000000000), nil
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
AccountingOpts: []mock.Option{mock.WithCompensatedBalanceFunc(compensatedBalanceFunc)}, AccountingOpts: []mock.Option{mock.WithCompensatedBalanceFunc(compensatedBalanceFunc)},
...@@ -88,7 +89,7 @@ func TestBalancesPeers(t *testing.T) { ...@@ -88,7 +89,7 @@ func TestBalancesPeers(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/balances/"+peer, http.StatusOK, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/balances/"+peer, http.StatusOK,
jsonhttptest.WithExpectedJSONResponse(debugapi.BalanceResponse{ jsonhttptest.WithExpectedJSONResponse(debugapi.BalanceResponse{
Peer: peer, Peer: peer,
Balance: 1000000000000000000, Balance: big.NewInt(100000000000000000),
}), }),
) )
} }
...@@ -96,8 +97,8 @@ func TestBalancesPeers(t *testing.T) { ...@@ -96,8 +97,8 @@ func TestBalancesPeers(t *testing.T) {
func TestBalancesPeersError(t *testing.T) { func TestBalancesPeersError(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
wantErr := errors.New("Error") wantErr := errors.New("Error")
compensatedBalanceFunc := func(swarm.Address) (int64, error) { compensatedBalanceFunc := func(swarm.Address) (*big.Int, error) {
return 0, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
AccountingOpts: []mock.Option{mock.WithCompensatedBalanceFunc(compensatedBalanceFunc)}, AccountingOpts: []mock.Option{mock.WithCompensatedBalanceFunc(compensatedBalanceFunc)},
...@@ -113,8 +114,8 @@ func TestBalancesPeersError(t *testing.T) { ...@@ -113,8 +114,8 @@ func TestBalancesPeersError(t *testing.T) {
func TestBalancesPeersNoBalance(t *testing.T) { func TestBalancesPeersNoBalance(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
compensatedBalanceFunc := func(swarm.Address) (int64, error) { compensatedBalanceFunc := func(swarm.Address) (*big.Int, error) {
return 0, accounting.ErrPeerNoBalance return nil, accounting.ErrPeerNoBalance
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
AccountingOpts: []mock.Option{mock.WithCompensatedBalanceFunc(compensatedBalanceFunc)}, AccountingOpts: []mock.Option{mock.WithCompensatedBalanceFunc(compensatedBalanceFunc)},
...@@ -172,11 +173,11 @@ func equalBalances(a, b *debugapi.BalancesResponse) bool { ...@@ -172,11 +173,11 @@ func equalBalances(a, b *debugapi.BalancesResponse) bool {
} }
func TestConsumedBalances(t *testing.T) { func TestConsumedBalances(t *testing.T) {
balancesFunc := func() (ret map[string]int64, err error) { balancesFunc := func() (ret map[string]*big.Int, err error) {
ret = make(map[string]int64) ret = make(map[string]*big.Int)
ret["DEAD"] = 1000000000000000000 ret["DEAD"] = big.NewInt(1000000000000000000)
ret["BEEF"] = -100000000000000000 ret["BEEF"] = big.NewInt(-100000000000000000)
ret["PARTY"] = 0 ret["PARTY"] = big.NewInt(0)
return ret, err return ret, err
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
...@@ -187,15 +188,15 @@ func TestConsumedBalances(t *testing.T) { ...@@ -187,15 +188,15 @@ func TestConsumedBalances(t *testing.T) {
[]debugapi.BalanceResponse{ []debugapi.BalanceResponse{
{ {
Peer: "DEAD", Peer: "DEAD",
Balance: 1000000000000000000, Balance: big.NewInt(1000000000000000000),
}, },
{ {
Peer: "BEEF", Peer: "BEEF",
Balance: -100000000000000000, Balance: big.NewInt(-100000000000000000),
}, },
{ {
Peer: "PARTY", Peer: "PARTY",
Balance: 0, Balance: big.NewInt(0),
}, },
}, },
} }
...@@ -214,7 +215,7 @@ func TestConsumedBalances(t *testing.T) { ...@@ -214,7 +215,7 @@ func TestConsumedBalances(t *testing.T) {
func TestConsumedError(t *testing.T) { func TestConsumedError(t *testing.T) {
wantErr := errors.New("ASDF") wantErr := errors.New("ASDF")
balancesFunc := func() (ret map[string]int64, err error) { balancesFunc := func() (ret map[string]*big.Int, err error) {
return nil, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
...@@ -231,8 +232,8 @@ func TestConsumedError(t *testing.T) { ...@@ -231,8 +232,8 @@ func TestConsumedError(t *testing.T) {
func TestConsumedPeers(t *testing.T) { func TestConsumedPeers(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
balanceFunc := func(swarm.Address) (int64, error) { balanceFunc := func(swarm.Address) (*big.Int, error) {
return 1000000000000000000, nil return big.NewInt(1000000000000000000), nil
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
AccountingOpts: []mock.Option{mock.WithBalanceFunc(balanceFunc)}, AccountingOpts: []mock.Option{mock.WithBalanceFunc(balanceFunc)},
...@@ -241,7 +242,7 @@ func TestConsumedPeers(t *testing.T) { ...@@ -241,7 +242,7 @@ func TestConsumedPeers(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/consumed/"+peer, http.StatusOK, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/consumed/"+peer, http.StatusOK,
jsonhttptest.WithExpectedJSONResponse(debugapi.BalanceResponse{ jsonhttptest.WithExpectedJSONResponse(debugapi.BalanceResponse{
Peer: peer, Peer: peer,
Balance: 1000000000000000000, Balance: big.NewInt(1000000000000000000),
}), }),
) )
} }
...@@ -249,8 +250,8 @@ func TestConsumedPeers(t *testing.T) { ...@@ -249,8 +250,8 @@ func TestConsumedPeers(t *testing.T) {
func TestConsumedPeersError(t *testing.T) { func TestConsumedPeersError(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
wantErr := errors.New("Error") wantErr := errors.New("Error")
balanceFunc := func(swarm.Address) (int64, error) { balanceFunc := func(swarm.Address) (*big.Int, error) {
return 0, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
AccountingOpts: []mock.Option{mock.WithBalanceFunc(balanceFunc)}, AccountingOpts: []mock.Option{mock.WithBalanceFunc(balanceFunc)},
...@@ -266,8 +267,8 @@ func TestConsumedPeersError(t *testing.T) { ...@@ -266,8 +267,8 @@ func TestConsumedPeersError(t *testing.T) {
func TestConsumedPeersNoBalance(t *testing.T) { func TestConsumedPeersNoBalance(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
balanceFunc := func(swarm.Address) (int64, error) { balanceFunc := func(swarm.Address) (*big.Int, error) {
return 0, accounting.ErrPeerNoBalance return nil, accounting.ErrPeerNoBalance
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
AccountingOpts: []mock.Option{mock.WithBalanceFunc(balanceFunc)}, AccountingOpts: []mock.Option{mock.WithBalanceFunc(balanceFunc)},
......
...@@ -19,7 +19,6 @@ import ( ...@@ -19,7 +19,6 @@ import (
p2pmock "github.com/ethersphere/bee/pkg/p2p/mock" p2pmock "github.com/ethersphere/bee/pkg/p2p/mock"
"github.com/ethersphere/bee/pkg/pingpong" "github.com/ethersphere/bee/pkg/pingpong"
"github.com/ethersphere/bee/pkg/resolver" "github.com/ethersphere/bee/pkg/resolver"
settlementmock "github.com/ethersphere/bee/pkg/settlement/pseudosettle/mock"
chequebookmock "github.com/ethersphere/bee/pkg/settlement/swap/chequebook/mock" chequebookmock "github.com/ethersphere/bee/pkg/settlement/swap/chequebook/mock"
swapmock "github.com/ethersphere/bee/pkg/settlement/swap/mock" swapmock "github.com/ethersphere/bee/pkg/settlement/swap/mock"
"github.com/ethersphere/bee/pkg/storage" "github.com/ethersphere/bee/pkg/storage"
...@@ -42,7 +41,7 @@ type testServerOptions struct { ...@@ -42,7 +41,7 @@ type testServerOptions struct {
TopologyOpts []topologymock.Option TopologyOpts []topologymock.Option
Tags *tags.Tags Tags *tags.Tags
AccountingOpts []accountingmock.Option AccountingOpts []accountingmock.Option
SettlementOpts []settlementmock.Option SettlementOpts []swapmock.Option
ChequebookOpts []chequebookmock.Option ChequebookOpts []chequebookmock.Option
SwapOpts []swapmock.Option SwapOpts []swapmock.Option
} }
...@@ -55,7 +54,7 @@ type testServer struct { ...@@ -55,7 +54,7 @@ type testServer struct {
func newTestServer(t *testing.T, o testServerOptions) *testServer { func newTestServer(t *testing.T, o testServerOptions) *testServer {
topologyDriver := topologymock.NewTopologyDriver(o.TopologyOpts...) topologyDriver := topologymock.NewTopologyDriver(o.TopologyOpts...)
acc := accountingmock.NewAccounting(o.AccountingOpts...) acc := accountingmock.NewAccounting(o.AccountingOpts...)
settlement := settlementmock.NewSettlement(o.SettlementOpts...) settlement := swapmock.New(o.SettlementOpts...)
chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...) chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...)
swapserv := swapmock.NewApiInterface(o.SwapOpts...) swapserv := swapmock.NewApiInterface(o.SwapOpts...)
s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, o.P2P, o.Pingpong, topologyDriver, o.Storer, logging.New(ioutil.Discard, 0), nil, o.Tags, acc, settlement, true, swapserv, chequebook) s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, o.P2P, o.Pingpong, topologyDriver, o.Storer, logging.New(ioutil.Discard, 0), nil, o.Tags, acc, settlement, true, swapserv, chequebook)
......
...@@ -21,9 +21,9 @@ var ( ...@@ -21,9 +21,9 @@ var (
) )
type settlementResponse struct { type settlementResponse struct {
Peer string `json:"peer"` Peer string `json:"peer"`
SettlementReceived uint64 `json:"received"` SettlementReceived *big.Int `json:"received"`
SettlementSent uint64 `json:"sent"` SettlementSent *big.Int `json:"sent"`
} }
type settlementsResponse struct { type settlementsResponse struct {
...@@ -58,9 +58,9 @@ func (s *server) settlementsHandler(w http.ResponseWriter, r *http.Request) { ...@@ -58,9 +58,9 @@ func (s *server) settlementsHandler(w http.ResponseWriter, r *http.Request) {
settlementResponses[a] = settlementResponse{ settlementResponses[a] = settlementResponse{
Peer: a, Peer: a,
SettlementSent: b, SettlementSent: b,
SettlementReceived: 0, SettlementReceived: big.NewInt(0),
} }
totalSent.Add(big.NewInt(int64(b)), totalSent) totalSent.Add(b, totalSent)
} }
for a, b := range settlementsReceived { for a, b := range settlementsReceived {
...@@ -71,11 +71,11 @@ func (s *server) settlementsHandler(w http.ResponseWriter, r *http.Request) { ...@@ -71,11 +71,11 @@ func (s *server) settlementsHandler(w http.ResponseWriter, r *http.Request) {
} else { } else {
settlementResponses[a] = settlementResponse{ settlementResponses[a] = settlementResponse{
Peer: a, Peer: a,
SettlementSent: 0, SettlementSent: big.NewInt(0),
SettlementReceived: b, SettlementReceived: b,
} }
} }
totalReceived.Add(big.NewInt(int64(b)), totalReceived) totalReceived.Add(b, totalReceived)
} }
settlementResponsesArray := make([]settlementResponse, len(settlementResponses)) settlementResponsesArray := make([]settlementResponse, len(settlementResponses))
......
...@@ -14,23 +14,23 @@ import ( ...@@ -14,23 +14,23 @@ import (
"github.com/ethersphere/bee/pkg/debugapi" "github.com/ethersphere/bee/pkg/debugapi"
"github.com/ethersphere/bee/pkg/jsonhttp" "github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest" "github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/settlement/pseudosettle/mock" "github.com/ethersphere/bee/pkg/settlement/swap/mock"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
) )
func TestSettlements(t *testing.T) { func TestSettlements(t *testing.T) {
settlementsSentFunc := func() (ret map[string]uint64, err error) { settlementsSentFunc := func() (ret map[string]*big.Int, err error) {
ret = make(map[string]uint64) ret = make(map[string]*big.Int)
ret["DEAD"] = 10000 ret["DEAD"] = big.NewInt(10000)
ret["BEEF"] = 20000 ret["BEEF"] = big.NewInt(20000)
ret["FFFF"] = 50000 ret["FFFF"] = big.NewInt(50000)
return ret, err return ret, err
} }
settlementsRecvFunc := func() (ret map[string]uint64, err error) { settlementsRecvFunc := func() (ret map[string]*big.Int, err error) {
ret = make(map[string]uint64) ret = make(map[string]*big.Int)
ret["BEEF"] = 10000 ret["BEEF"] = big.NewInt(10000)
ret["EEEE"] = 5000 ret["EEEE"] = big.NewInt(5000)
return ret, err return ret, err
} }
...@@ -44,23 +44,23 @@ func TestSettlements(t *testing.T) { ...@@ -44,23 +44,23 @@ func TestSettlements(t *testing.T) {
Settlements: []debugapi.SettlementResponse{ Settlements: []debugapi.SettlementResponse{
{ {
Peer: "DEAD", Peer: "DEAD",
SettlementReceived: 0, SettlementReceived: big.NewInt(0),
SettlementSent: 10000, SettlementSent: big.NewInt(10000),
}, },
{ {
Peer: "BEEF", Peer: "BEEF",
SettlementReceived: 10000, SettlementReceived: big.NewInt(10000),
SettlementSent: 20000, SettlementSent: big.NewInt(20000),
}, },
{ {
Peer: "FFFF", Peer: "FFFF",
SettlementReceived: 0, SettlementReceived: big.NewInt(0),
SettlementSent: 50000, SettlementSent: big.NewInt(50000),
}, },
{ {
Peer: "EEEE", Peer: "EEEE",
SettlementReceived: 5000, SettlementReceived: big.NewInt(5000),
SettlementSent: 0, SettlementSent: big.NewInt(0),
}, },
}, },
} }
...@@ -79,7 +79,7 @@ func TestSettlements(t *testing.T) { ...@@ -79,7 +79,7 @@ func TestSettlements(t *testing.T) {
func TestSettlementsError(t *testing.T) { func TestSettlementsError(t *testing.T) {
wantErr := errors.New("New errors") wantErr := errors.New("New errors")
settlementsSentFunc := func() (map[string]uint64, error) { settlementsSentFunc := func() (map[string]*big.Int, error) {
return nil, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
...@@ -96,8 +96,8 @@ func TestSettlementsError(t *testing.T) { ...@@ -96,8 +96,8 @@ func TestSettlementsError(t *testing.T) {
func TestSettlementsPeers(t *testing.T) { func TestSettlementsPeers(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
settlementSentFunc := func(swarm.Address) (uint64, error) { settlementSentFunc := func(swarm.Address) (*big.Int, error) {
return 1000000000000000000, nil return big.NewInt(1000000000000000000), nil
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)}, SettlementOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)},
...@@ -106,8 +106,8 @@ func TestSettlementsPeers(t *testing.T) { ...@@ -106,8 +106,8 @@ func TestSettlementsPeers(t *testing.T) {
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusOK, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusOK,
jsonhttptest.WithExpectedJSONResponse(debugapi.SettlementResponse{ jsonhttptest.WithExpectedJSONResponse(debugapi.SettlementResponse{
Peer: peer, Peer: peer,
SettlementSent: 1000000000000000000, SettlementSent: big.NewInt(1000000000000000000),
SettlementReceived: 0, SettlementReceived: big.NewInt(0),
}), }),
) )
} }
...@@ -115,8 +115,8 @@ func TestSettlementsPeers(t *testing.T) { ...@@ -115,8 +115,8 @@ func TestSettlementsPeers(t *testing.T) {
func TestSettlementsPeersError(t *testing.T) { func TestSettlementsPeersError(t *testing.T) {
peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa" peer := "bff2c89e85e78c38bd89fca1acc996afb876c21bf5a8482ad798ce15f1c223fa"
wantErr := errors.New("Error") wantErr := errors.New("Error")
settlementSentFunc := func(swarm.Address) (uint64, error) { settlementSentFunc := func(swarm.Address) (*big.Int, error) {
return 0, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)}, SettlementOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)},
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"fmt" "fmt"
"io" "io"
"log" "log"
"math/big"
"net" "net"
"net/http" "net/http"
"path/filepath" "path/filepath"
...@@ -97,14 +98,14 @@ type Options struct { ...@@ -97,14 +98,14 @@ type Options struct {
TracingEndpoint string TracingEndpoint string
TracingServiceName string TracingServiceName string
GlobalPinningEnabled bool GlobalPinningEnabled bool
PaymentThreshold uint64 PaymentThreshold string
PaymentTolerance uint64 PaymentTolerance string
PaymentEarly uint64 PaymentEarly string
ResolverConnectionCfgs []multiresolver.ConnectionConfig ResolverConnectionCfgs []multiresolver.ConnectionConfig
GatewayMode bool GatewayMode bool
SwapEndpoint string SwapEndpoint string
SwapFactoryAddress string SwapFactoryAddress string
SwapInitialDeposit uint64 SwapInitialDeposit string
SwapEnable bool SwapEnable bool
} }
...@@ -198,12 +199,16 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -198,12 +199,16 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
} }
} }
swapInitialDeposit, ok := new(big.Int).SetString(o.SwapInitialDeposit, 10)
if !ok {
return nil, fmt.Errorf("invalid initial deposit: %s", swapInitialDeposit)
}
// initialize chequebook logic // initialize chequebook logic
chequebookService, err = chequebook.Init(p2pCtx, chequebookService, err = chequebook.Init(p2pCtx,
chequebookFactory, chequebookFactory,
stateStore, stateStore,
logger, logger,
o.SwapInitialDeposit, swapInitialDeposit,
transactionService, transactionService,
swapBackend, swapBackend,
chainID.Int64(), chainID.Int64(),
...@@ -300,12 +305,32 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -300,12 +305,32 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
settlement = pseudosettleService settlement = pseudosettleService
} }
pricing := pricing.New(p2ps, logger, o.PaymentThreshold) paymentThreshold, ok := new(big.Int).SetString(o.PaymentThreshold, 10)
if !ok {
return nil, fmt.Errorf("invalid payment threshold: %s", paymentThreshold)
}
pricing := pricing.New(p2ps, logger, paymentThreshold)
if err = p2ps.AddProtocol(pricing.Protocol()); err != nil { if err = p2ps.AddProtocol(pricing.Protocol()); err != nil {
return nil, fmt.Errorf("pricing service: %w", err) return nil, fmt.Errorf("pricing service: %w", err)
} }
acc, err := accounting.NewAccounting(o.PaymentThreshold, o.PaymentTolerance, o.PaymentEarly, logger, stateStore, settlement, pricing) paymentTolerance, ok := new(big.Int).SetString(o.PaymentTolerance, 10)
if !ok {
return nil, fmt.Errorf("invalid payment tolerance: %s", paymentTolerance)
}
paymentEarly, ok := new(big.Int).SetString(o.PaymentEarly, 10)
if !ok {
return nil, fmt.Errorf("invalid payment early: %s", paymentEarly)
}
acc, err := accounting.NewAccounting(
paymentThreshold,
paymentTolerance,
paymentEarly,
logger,
stateStore,
settlement,
pricing,
)
if err != nil { if err != nil {
return nil, fmt.Errorf("accounting: %w", err) return nil, fmt.Errorf("accounting: %w", err)
} }
......
...@@ -23,7 +23,7 @@ var _ = math.Inf ...@@ -23,7 +23,7 @@ var _ = math.Inf
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type AnnouncePaymentThreshold struct { type AnnouncePaymentThreshold struct {
PaymentThreshold uint64 `protobuf:"varint,1,opt,name=PaymentThreshold,proto3" json:"PaymentThreshold,omitempty"` PaymentThreshold []byte `protobuf:"bytes,1,opt,name=PaymentThreshold,proto3" json:"PaymentThreshold,omitempty"`
} }
func (m *AnnouncePaymentThreshold) Reset() { *m = AnnouncePaymentThreshold{} } func (m *AnnouncePaymentThreshold) Reset() { *m = AnnouncePaymentThreshold{} }
...@@ -59,11 +59,11 @@ func (m *AnnouncePaymentThreshold) XXX_DiscardUnknown() { ...@@ -59,11 +59,11 @@ func (m *AnnouncePaymentThreshold) XXX_DiscardUnknown() {
var xxx_messageInfo_AnnouncePaymentThreshold proto.InternalMessageInfo var xxx_messageInfo_AnnouncePaymentThreshold proto.InternalMessageInfo
func (m *AnnouncePaymentThreshold) GetPaymentThreshold() uint64 { func (m *AnnouncePaymentThreshold) GetPaymentThreshold() []byte {
if m != nil { if m != nil {
return m.PaymentThreshold return m.PaymentThreshold
} }
return 0 return nil
} }
func init() { func init() {
...@@ -78,10 +78,10 @@ var fileDescriptor_ec4cc93d045d43d0 = []byte{ ...@@ -78,10 +78,10 @@ var fileDescriptor_ec4cc93d045d43d0 = []byte{
0xce, 0xcc, 0x4b, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0x95, 0xdc, 0xb8, 0xce, 0xcc, 0x4b, 0xd7, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x87, 0x72, 0x95, 0xdc, 0xb8,
0x24, 0x1c, 0xf3, 0xf2, 0xf2, 0x4b, 0xf3, 0x92, 0x53, 0x03, 0x12, 0x2b, 0x73, 0x53, 0xf3, 0x4a, 0x24, 0x1c, 0xf3, 0xf2, 0xf2, 0x4b, 0xf3, 0x92, 0x53, 0x03, 0x12, 0x2b, 0x73, 0x53, 0xf3, 0x4a,
0x42, 0x32, 0x8a, 0x52, 0x8b, 0x33, 0xf2, 0x73, 0x52, 0x84, 0xb4, 0xb8, 0x04, 0xd0, 0xc5, 0x24, 0x42, 0x32, 0x8a, 0x52, 0x8b, 0x33, 0xf2, 0x73, 0x52, 0x84, 0xb4, 0xb8, 0x04, 0xd0, 0xc5, 0x24,
0x18, 0x15, 0x18, 0x35, 0x58, 0x82, 0x30, 0xc4, 0x9d, 0x64, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x30, 0xc4, 0x9d, 0x64, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0,
0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8,
0xf1, 0x58, 0x8e, 0x21, 0x8a, 0xa9, 0x20, 0x29, 0x89, 0x0d, 0x6c, 0xab, 0x31, 0x20, 0x00, 0x00, 0xf1, 0x58, 0x8e, 0x21, 0x8a, 0xa9, 0x20, 0x29, 0x89, 0x0d, 0x6c, 0xab, 0x31, 0x20, 0x00, 0x00,
0xff, 0xff, 0x70, 0x59, 0x58, 0xcf, 0x86, 0x00, 0x00, 0x00, 0xff, 0xff, 0x50, 0xca, 0x0e, 0x0a, 0x86, 0x00, 0x00, 0x00,
} }
func (m *AnnouncePaymentThreshold) Marshal() (dAtA []byte, err error) { func (m *AnnouncePaymentThreshold) Marshal() (dAtA []byte, err error) {
...@@ -104,10 +104,12 @@ func (m *AnnouncePaymentThreshold) MarshalToSizedBuffer(dAtA []byte) (int, error ...@@ -104,10 +104,12 @@ func (m *AnnouncePaymentThreshold) MarshalToSizedBuffer(dAtA []byte) (int, error
_ = i _ = i
var l int var l int
_ = l _ = l
if m.PaymentThreshold != 0 { if len(m.PaymentThreshold) > 0 {
i = encodeVarintPricing(dAtA, i, uint64(m.PaymentThreshold)) i -= len(m.PaymentThreshold)
copy(dAtA[i:], m.PaymentThreshold)
i = encodeVarintPricing(dAtA, i, uint64(len(m.PaymentThreshold)))
i-- i--
dAtA[i] = 0x8 dAtA[i] = 0xa
} }
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
...@@ -129,8 +131,9 @@ func (m *AnnouncePaymentThreshold) Size() (n int) { ...@@ -129,8 +131,9 @@ func (m *AnnouncePaymentThreshold) Size() (n int) {
} }
var l int var l int
_ = l _ = l
if m.PaymentThreshold != 0 { l = len(m.PaymentThreshold)
n += 1 + sovPricing(uint64(m.PaymentThreshold)) if l > 0 {
n += 1 + l + sovPricing(uint64(l))
} }
return n return n
} }
...@@ -171,10 +174,10 @@ func (m *AnnouncePaymentThreshold) Unmarshal(dAtA []byte) error { ...@@ -171,10 +174,10 @@ func (m *AnnouncePaymentThreshold) Unmarshal(dAtA []byte) error {
} }
switch fieldNum { switch fieldNum {
case 1: case 1:
if wireType != 0 { if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field PaymentThreshold", wireType) return fmt.Errorf("proto: wrong wireType = %d for field PaymentThreshold", wireType)
} }
m.PaymentThreshold = 0 var byteLen int
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowPricing return ErrIntOverflowPricing
...@@ -184,11 +187,26 @@ func (m *AnnouncePaymentThreshold) Unmarshal(dAtA []byte) error { ...@@ -184,11 +187,26 @@ func (m *AnnouncePaymentThreshold) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.PaymentThreshold |= uint64(b&0x7F) << shift byteLen |= int(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
} }
if byteLen < 0 {
return ErrInvalidLengthPricing
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthPricing
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.PaymentThreshold = append(m.PaymentThreshold[:0], dAtA[iNdEx:postIndex]...)
if m.PaymentThreshold == nil {
m.PaymentThreshold = []byte{}
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipPricing(dAtA[iNdEx:]) skippy, err := skipPricing(dAtA[iNdEx:])
......
...@@ -9,5 +9,5 @@ package pricing; ...@@ -9,5 +9,5 @@ package pricing;
option go_package = "pb"; option go_package = "pb";
message AnnouncePaymentThreshold { message AnnouncePaymentThreshold {
uint64 PaymentThreshold = 1; bytes PaymentThreshold = 1;
} }
...@@ -7,6 +7,7 @@ package pricing ...@@ -7,6 +7,7 @@ package pricing
import ( import (
"context" "context"
"fmt" "fmt"
"math/big"
"time" "time"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
...@@ -26,22 +27,22 @@ var _ Interface = (*Service)(nil) ...@@ -26,22 +27,22 @@ var _ Interface = (*Service)(nil)
// Interface is the main interface of the pricing protocol // Interface is the main interface of the pricing protocol
type Interface interface { type Interface interface {
AnnouncePaymentThreshold(ctx context.Context, peer swarm.Address, paymentThreshold uint64) error AnnouncePaymentThreshold(ctx context.Context, peer swarm.Address, paymentThreshold *big.Int) error
} }
// PaymentThresholdObserver is used for being notified of payment threshold updates // PaymentThresholdObserver is used for being notified of payment threshold updates
type PaymentThresholdObserver interface { type PaymentThresholdObserver interface {
NotifyPaymentThreshold(peer swarm.Address, paymentThreshold uint64) error NotifyPaymentThreshold(peer swarm.Address, paymentThreshold *big.Int) error
} }
type Service struct { type Service struct {
streamer p2p.Streamer streamer p2p.Streamer
logger logging.Logger logger logging.Logger
paymentThreshold uint64 paymentThreshold *big.Int
paymentThresholdObserver PaymentThresholdObserver paymentThresholdObserver PaymentThresholdObserver
} }
func New(streamer p2p.Streamer, logger logging.Logger, paymentThreshold uint64) *Service { func New(streamer p2p.Streamer, logger logging.Logger, paymentThreshold *big.Int) *Service {
return &Service{ return &Service{
streamer: streamer, streamer: streamer,
logger: logger, logger: logger,
...@@ -81,7 +82,7 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e ...@@ -81,7 +82,7 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e
} }
s.logger.Tracef("received payment threshold announcement from peer %v of %d", p.Address, req.PaymentThreshold) s.logger.Tracef("received payment threshold announcement from peer %v of %d", p.Address, req.PaymentThreshold)
return s.paymentThresholdObserver.NotifyPaymentThreshold(p.Address, req.PaymentThreshold) return s.paymentThresholdObserver.NotifyPaymentThreshold(p.Address, big.NewInt(0).SetBytes(req.PaymentThreshold))
} }
func (s *Service) init(ctx context.Context, p p2p.Peer) error { func (s *Service) init(ctx context.Context, p p2p.Peer) error {
...@@ -93,7 +94,7 @@ func (s *Service) init(ctx context.Context, p p2p.Peer) error { ...@@ -93,7 +94,7 @@ func (s *Service) init(ctx context.Context, p p2p.Peer) error {
} }
// AnnouncePaymentThreshold announces the payment threshold to per // AnnouncePaymentThreshold announces the payment threshold to per
func (s *Service) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Address, paymentThreshold uint64) error { func (s *Service) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Address, paymentThreshold *big.Int) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second) ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() defer cancel()
...@@ -112,7 +113,7 @@ func (s *Service) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Addre ...@@ -112,7 +113,7 @@ func (s *Service) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Addre
s.logger.Tracef("sending payment threshold announcement to peer %v of %d", peer, paymentThreshold) s.logger.Tracef("sending payment threshold announcement to peer %v of %d", peer, paymentThreshold)
w := protobuf.NewWriter(stream) w := protobuf.NewWriter(stream)
err = w.WriteMsgWithContext(ctx, &pb.AnnouncePaymentThreshold{ err = w.WriteMsgWithContext(ctx, &pb.AnnouncePaymentThreshold{
PaymentThreshold: paymentThreshold, PaymentThreshold: paymentThreshold.Bytes(),
}) })
return err return err
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"context" "context"
"io/ioutil" "io/ioutil"
"math/big"
"testing" "testing"
"github.com/ethersphere/bee/pkg/logging" "github.com/ethersphere/bee/pkg/logging"
...@@ -21,10 +22,10 @@ import ( ...@@ -21,10 +22,10 @@ import (
type testObserver struct { type testObserver struct {
called bool called bool
peer swarm.Address peer swarm.Address
paymentThreshold uint64 paymentThreshold *big.Int
} }
func (t *testObserver) NotifyPaymentThreshold(peer swarm.Address, paymentThreshold uint64) error { func (t *testObserver) NotifyPaymentThreshold(peer swarm.Address, paymentThreshold *big.Int) error {
t.called = true t.called = true
t.peer = peer t.peer = peer
t.paymentThreshold = paymentThreshold t.paymentThreshold = paymentThreshold
...@@ -33,7 +34,7 @@ func (t *testObserver) NotifyPaymentThreshold(peer swarm.Address, paymentThresho ...@@ -33,7 +34,7 @@ func (t *testObserver) NotifyPaymentThreshold(peer swarm.Address, paymentThresho
func TestAnnouncePaymentThreshold(t *testing.T) { func TestAnnouncePaymentThreshold(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
testThreshold := uint64(100000) testThreshold := big.NewInt(100000)
observer := &testObserver{} observer := &testObserver{}
recipient := pricing.New(nil, logger, testThreshold) recipient := pricing.New(nil, logger, testThreshold)
...@@ -46,7 +47,7 @@ func TestAnnouncePaymentThreshold(t *testing.T) { ...@@ -46,7 +47,7 @@ func TestAnnouncePaymentThreshold(t *testing.T) {
payer := pricing.New(recorder, logger, testThreshold) payer := pricing.New(recorder, logger, testThreshold)
peerID := swarm.MustParseHexAddress("9ee7add7") peerID := swarm.MustParseHexAddress("9ee7add7")
paymentThreshold := uint64(10000) paymentThreshold := big.NewInt(10000)
err := payer.AnnouncePaymentThreshold(context.Background(), peerID, paymentThreshold) err := payer.AnnouncePaymentThreshold(context.Background(), peerID, paymentThreshold)
if err != nil { if err != nil {
...@@ -76,8 +77,8 @@ func TestAnnouncePaymentThreshold(t *testing.T) { ...@@ -76,8 +77,8 @@ func TestAnnouncePaymentThreshold(t *testing.T) {
t.Fatalf("got %v messages, want %v", len(messages), 1) t.Fatalf("got %v messages, want %v", len(messages), 1)
} }
sentPaymentThreshold := messages[0].(*pb.AnnouncePaymentThreshold).PaymentThreshold sentPaymentThreshold := big.NewInt(0).SetBytes(messages[0].(*pb.AnnouncePaymentThreshold).PaymentThreshold)
if sentPaymentThreshold != paymentThreshold { if sentPaymentThreshold.Cmp(paymentThreshold) != 0 {
t.Fatalf("got message with amount %v, want %v", sentPaymentThreshold, paymentThreshold) t.Fatalf("got message with amount %v, want %v", sentPaymentThreshold, paymentThreshold)
} }
...@@ -85,7 +86,7 @@ func TestAnnouncePaymentThreshold(t *testing.T) { ...@@ -85,7 +86,7 @@ func TestAnnouncePaymentThreshold(t *testing.T) {
t.Fatal("expected observer to be called") t.Fatal("expected observer to be called")
} }
if observer.paymentThreshold != paymentThreshold { if observer.paymentThreshold.Cmp(paymentThreshold) != 0 {
t.Fatalf("observer called with wrong paymentThreshold. got %d, want %d", observer.paymentThreshold, paymentThreshold) t.Fatalf("observer called with wrong paymentThreshold. got %d, want %d", observer.paymentThreshold, paymentThreshold)
} }
......
...@@ -76,7 +76,7 @@ func TestSendChunkAndReceiveReceipt(t *testing.T) { ...@@ -76,7 +76,7 @@ func TestSendChunkAndReceiveReceipt(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != -int64(fixedPrice) { if balance.Int64() != -int64(fixedPrice) {
t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance) t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance)
} }
...@@ -85,7 +85,7 @@ func TestSendChunkAndReceiveReceipt(t *testing.T) { ...@@ -85,7 +85,7 @@ func TestSendChunkAndReceiveReceipt(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != int64(fixedPrice) { if balance.Int64() != int64(fixedPrice) {
t.Fatalf("unexpected balance on peer. want %d got %d", int64(fixedPrice), balance) t.Fatalf("unexpected balance on peer. want %d got %d", int64(fixedPrice), balance)
} }
} }
...@@ -155,7 +155,7 @@ func TestPushChunkToClosest(t *testing.T) { ...@@ -155,7 +155,7 @@ func TestPushChunkToClosest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != -int64(fixedPrice) { if balance.Int64() != -int64(fixedPrice) {
t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance) t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance)
} }
...@@ -164,7 +164,7 @@ func TestPushChunkToClosest(t *testing.T) { ...@@ -164,7 +164,7 @@ func TestPushChunkToClosest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != int64(fixedPrice) { if balance.Int64() != int64(fixedPrice) {
t.Fatalf("unexpected balance on peer. want %d got %d", int64(fixedPrice), balance) t.Fatalf("unexpected balance on peer. want %d got %d", int64(fixedPrice), balance)
} }
...@@ -273,7 +273,7 @@ func TestPushChunkToNextClosest(t *testing.T) { ...@@ -273,7 +273,7 @@ func TestPushChunkToNextClosest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != -int64(fixedPrice) { if balance.Int64() != -int64(fixedPrice) {
t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance) t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance)
} }
...@@ -282,7 +282,7 @@ func TestPushChunkToNextClosest(t *testing.T) { ...@@ -282,7 +282,7 @@ func TestPushChunkToNextClosest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance2 != int64(fixedPrice) { if balance2.Int64() != int64(fixedPrice) {
t.Fatalf("unexpected balance on peer2. want %d got %d", int64(fixedPrice), balance2) t.Fatalf("unexpected balance on peer2. want %d got %d", int64(fixedPrice), balance2)
} }
...@@ -291,7 +291,7 @@ func TestPushChunkToNextClosest(t *testing.T) { ...@@ -291,7 +291,7 @@ func TestPushChunkToNextClosest(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance1 != 0 { if balance1.Int64() != 0 {
t.Fatalf("unexpected balance on peer1. want %d got %d", 0, balance1) t.Fatalf("unexpected balance on peer1. want %d got %d", 0, balance1)
} }
} }
...@@ -354,7 +354,7 @@ func TestHandler(t *testing.T) { ...@@ -354,7 +354,7 @@ func TestHandler(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != -int64(fixedPrice) { if balance.Int64() != -int64(fixedPrice) {
t.Fatalf("unexpected balance on trigger. want %d got %d", -int64(fixedPrice), balance) t.Fatalf("unexpected balance on trigger. want %d got %d", -int64(fixedPrice), balance)
} }
...@@ -364,7 +364,7 @@ func TestHandler(t *testing.T) { ...@@ -364,7 +364,7 @@ func TestHandler(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != int64(fixedPrice) { if balance.Int64() != int64(fixedPrice) {
t.Fatalf("unexpected balance on pivot. want %d got %d", int64(fixedPrice), balance) t.Fatalf("unexpected balance on pivot. want %d got %d", int64(fixedPrice), balance)
} }
...@@ -373,7 +373,7 @@ func TestHandler(t *testing.T) { ...@@ -373,7 +373,7 @@ func TestHandler(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != -int64(fixedPrice) { if balance.Int64() != -int64(fixedPrice) {
t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance) t.Fatalf("unexpected balance on pivot. want %d got %d", -int64(fixedPrice), balance)
} }
...@@ -382,7 +382,7 @@ func TestHandler(t *testing.T) { ...@@ -382,7 +382,7 @@ func TestHandler(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if balance != int64(fixedPrice) { if balance.Int64() != int64(fixedPrice) {
t.Fatalf("unexpected balance on closest. want %d got %d", int64(fixedPrice), balance) t.Fatalf("unexpected balance on closest. want %d got %d", int64(fixedPrice), balance)
} }
} }
......
...@@ -120,12 +120,12 @@ func TestDelivery(t *testing.T) { ...@@ -120,12 +120,12 @@ func TestDelivery(t *testing.T) {
} }
clientBalance, _ := clientMockAccounting.Balance(peerID) clientBalance, _ := clientMockAccounting.Balance(peerID)
if clientBalance != -int64(price) { if clientBalance.Int64() != -int64(price) {
t.Fatalf("unexpected balance on client. want %d got %d", -price, clientBalance) t.Fatalf("unexpected balance on client. want %d got %d", -price, clientBalance)
} }
serverBalance, _ := serverMockAccounting.Balance(peerID) serverBalance, _ := serverMockAccounting.Balance(peerID)
if serverBalance != int64(price) { if serverBalance.Int64() != int64(price) {
t.Fatalf("unexpected balance on server. want %d got %d", price, serverBalance) t.Fatalf("unexpected balance on server. want %d got %d", price, serverBalance)
} }
} }
...@@ -418,12 +418,12 @@ func TestRetrievePreemptiveRetry(t *testing.T) { ...@@ -418,12 +418,12 @@ func TestRetrievePreemptiveRetry(t *testing.T) {
} }
clientServer1Balance, _ := clientMockAccounting.Balance(serverAddress1) clientServer1Balance, _ := clientMockAccounting.Balance(serverAddress1)
if clientServer1Balance != 0 { if clientServer1Balance.Int64() != 0 {
t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer1Balance) t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer1Balance)
} }
clientServer2Balance, _ := clientMockAccounting.Balance(serverAddress2) clientServer2Balance, _ := clientMockAccounting.Balance(serverAddress2)
if clientServer2Balance != -int64(price) { if clientServer2Balance.Int64() != -int64(price) {
t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer2Balance) t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer2Balance)
} }
...@@ -432,12 +432,12 @@ func TestRetrievePreemptiveRetry(t *testing.T) { ...@@ -432,12 +432,12 @@ func TestRetrievePreemptiveRetry(t *testing.T) {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
clientServer1Balance, _ = clientMockAccounting.Balance(serverAddress1) clientServer1Balance, _ = clientMockAccounting.Balance(serverAddress1)
if clientServer1Balance != -int64(price) { if clientServer1Balance.Int64() != -int64(price) {
t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer1Balance) t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer1Balance)
} }
clientServer2Balance, _ = clientMockAccounting.Balance(serverAddress2) clientServer2Balance, _ = clientMockAccounting.Balance(serverAddress2)
if clientServer2Balance != -int64(price) { if clientServer2Balance.Int64() != -int64(price) {
t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer2Balance) t.Fatalf("unexpected balance on client. want %d got %d", -price, clientServer2Balance)
} }
}) })
......
...@@ -7,6 +7,7 @@ package settlement ...@@ -7,6 +7,7 @@ package settlement
import ( import (
"context" "context"
"errors" "errors"
"math/big"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
) )
...@@ -19,18 +20,18 @@ var ( ...@@ -19,18 +20,18 @@ var (
type Interface interface { type Interface interface {
// Pay initiates a payment to the given peer // Pay initiates a payment to the given peer
// It should return without error it is likely that the payment worked // It should return without error it is likely that the payment worked
Pay(ctx context.Context, peer swarm.Address, amount uint64) error Pay(ctx context.Context, peer swarm.Address, amount *big.Int) error
// TotalSent returns the total amount sent to a peer // TotalSent returns the total amount sent to a peer
TotalSent(peer swarm.Address) (totalSent uint64, err error) TotalSent(peer swarm.Address) (totalSent *big.Int, err error)
// TotalReceived returns the total amount received from a peer // TotalReceived returns the total amount received from a peer
TotalReceived(peer swarm.Address) (totalSent uint64, err error) TotalReceived(peer swarm.Address) (totalSent *big.Int, err error)
// SettlementsSent returns sent settlements for each individual known peer // SettlementsSent returns sent settlements for each individual known peer
SettlementsSent() (map[string]uint64, error) SettlementsSent() (map[string]*big.Int, error)
// SettlementsReceived returns received settlements for each individual known peer // SettlementsReceived returns received settlements for each individual known peer
SettlementsReceived() (map[string]uint64, error) SettlementsReceived() (map[string]*big.Int, error)
// SetNotifyPaymentFunc sets the NotifyPaymentFunc to notify // SetNotifyPaymentFunc sets the NotifyPaymentFunc to notify
SetNotifyPaymentFunc(notifyPaymentFunc NotifyPaymentFunc) SetNotifyPaymentFunc(notifyPaymentFunc NotifyPaymentFunc)
} }
// NotifyPaymentFunc is called when a payment from peer was successfully received // NotifyPaymentFunc is called when a payment from peer was successfully received
type NotifyPaymentFunc func(peer swarm.Address, amount uint64) error type NotifyPaymentFunc func(peer swarm.Address, amount *big.Int) error
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mock
import (
"context"
"sync"
"github.com/ethersphere/bee/pkg/settlement"
"github.com/ethersphere/bee/pkg/swarm"
)
// Service is the mock settlement service.
type Service struct {
lock sync.Mutex
settlementsSent map[string]uint64
settlementsRecv map[string]uint64
settlementSentFunc func(swarm.Address) (uint64, error)
settlementRecvFunc func(swarm.Address) (uint64, error)
settlementsSentFunc func() (map[string]uint64, error)
settlementsRecvFunc func() (map[string]uint64, error)
payFunc func(context.Context, swarm.Address, uint64) error
}
// WithsettlementFunc sets the mock settlement function
func WithSettlementSentFunc(f func(swarm.Address) (uint64, error)) Option {
return optionFunc(func(s *Service) {
s.settlementSentFunc = f
})
}
func WithSettlementRecvFunc(f func(swarm.Address) (uint64, error)) Option {
return optionFunc(func(s *Service) {
s.settlementRecvFunc = f
})
}
// WithsettlementsFunc sets the mock settlements function
func WithSettlementsSentFunc(f func() (map[string]uint64, error)) Option {
return optionFunc(func(s *Service) {
s.settlementsSentFunc = f
})
}
func WithSettlementsRecvFunc(f func() (map[string]uint64, error)) Option {
return optionFunc(func(s *Service) {
s.settlementsRecvFunc = f
})
}
func WithPayFunc(f func(context.Context, swarm.Address, uint64) error) Option {
return optionFunc(func(s *Service) {
s.payFunc = f
})
}
// Newsettlement creates the mock settlement implementation
func NewSettlement(opts ...Option) settlement.Interface {
mock := new(Service)
mock.settlementsSent = make(map[string]uint64)
mock.settlementsRecv = make(map[string]uint64)
for _, o := range opts {
o.apply(mock)
}
return mock
}
func (s *Service) Pay(c context.Context, peer swarm.Address, amount uint64) error {
if s.payFunc != nil {
return s.payFunc(c, peer, amount)
}
s.settlementsSent[peer.String()] += amount
return nil
}
func (s *Service) TotalSent(peer swarm.Address) (totalSent uint64, err error) {
if s.settlementSentFunc != nil {
return s.settlementSentFunc(peer)
}
s.lock.Lock()
defer s.lock.Unlock()
return s.settlementsSent[peer.String()], nil
}
func (s *Service) TotalReceived(peer swarm.Address) (totalSent uint64, err error) {
if s.settlementRecvFunc != nil {
return s.settlementRecvFunc(peer)
}
s.lock.Lock()
defer s.lock.Unlock()
return s.settlementsRecv[peer.String()], nil
}
// settlements is the mock function wrapper that calls the set implementation
func (s *Service) SettlementsSent() (map[string]uint64, error) {
if s.settlementsSentFunc != nil {
return s.settlementsSentFunc()
}
s.lock.Lock()
defer s.lock.Unlock()
return s.settlementsSent, nil
}
func (s *Service) SettlementsReceived() (map[string]uint64, error) {
if s.settlementsRecvFunc != nil {
return s.settlementsRecvFunc()
}
s.lock.Lock()
defer s.lock.Unlock()
return s.settlementsRecv, nil
}
func (s *Service) SetNotifyPaymentFunc(settlement.NotifyPaymentFunc) {
}
// Option is the option passed to the mock settlement service
type Option interface {
apply(*Service)
}
type optionFunc func(*Service)
func (f optionFunc) apply(r *Service) { f(r) }
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"math/big"
"strings" "strings"
"time" "time"
...@@ -97,19 +98,19 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e ...@@ -97,19 +98,19 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e
if !errors.Is(err, settlement.ErrPeerNoSettlements) { if !errors.Is(err, settlement.ErrPeerNoSettlements) {
return err return err
} }
totalReceived = 0 totalReceived = big.NewInt(0)
} }
err = s.store.Put(totalKey(p.Address, SettlementReceivedPrefix), totalReceived+req.Amount) err = s.store.Put(totalKey(p.Address, SettlementReceivedPrefix), totalReceived.Add(totalReceived, new(big.Int).SetUint64(req.Amount)))
if err != nil { if err != nil {
return err return err
} }
return s.notifyPaymentFunc(p.Address, req.Amount) return s.notifyPaymentFunc(p.Address, new(big.Int).SetUint64(req.Amount))
} }
// Pay initiates a payment to the given peer // Pay initiates a payment to the given peer
func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) error { func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int) error {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second) ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel() defer cancel()
...@@ -128,7 +129,7 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er ...@@ -128,7 +129,7 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er
s.logger.Tracef("sending payment message to peer %v of %d", peer, amount) s.logger.Tracef("sending payment message to peer %v of %d", peer, amount)
w := protobuf.NewWriter(stream) w := protobuf.NewWriter(stream)
err = w.WriteMsgWithContext(ctx, &pb.Payment{ err = w.WriteMsgWithContext(ctx, &pb.Payment{
Amount: amount, Amount: amount.Uint64(),
}) })
if err != nil { if err != nil {
return err return err
...@@ -138,13 +139,15 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er ...@@ -138,13 +139,15 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er
if !errors.Is(err, settlement.ErrPeerNoSettlements) { if !errors.Is(err, settlement.ErrPeerNoSettlements) {
return err return err
} }
totalSent = 0 totalSent = big.NewInt(0)
} }
err = s.store.Put(totalKey(peer, SettlementSentPrefix), totalSent+amount) err = s.store.Put(totalKey(peer, SettlementSentPrefix), totalSent.Add(totalSent, amount))
if err != nil { if err != nil {
return err return err
} }
s.metrics.TotalSentPseudoSettlements.Add(float64(amount))
amountFloat, _ := new(big.Float).SetInt(amount).Float64()
s.metrics.TotalSentPseudoSettlements.Add(amountFloat)
return nil return nil
} }
...@@ -154,41 +157,41 @@ func (s *Service) SetNotifyPaymentFunc(notifyPaymentFunc settlement.NotifyPaymen ...@@ -154,41 +157,41 @@ func (s *Service) SetNotifyPaymentFunc(notifyPaymentFunc settlement.NotifyPaymen
} }
// TotalSent returns the total amount sent to a peer // TotalSent returns the total amount sent to a peer
func (s *Service) TotalSent(peer swarm.Address) (totalSent uint64, err error) { func (s *Service) TotalSent(peer swarm.Address) (totalSent *big.Int, err error) {
key := totalKey(peer, SettlementSentPrefix) key := totalKey(peer, SettlementSentPrefix)
err = s.store.Get(key, &totalSent) err = s.store.Get(key, &totalSent)
if err != nil { if err != nil {
if errors.Is(err, storage.ErrNotFound) { if errors.Is(err, storage.ErrNotFound) {
return 0, settlement.ErrPeerNoSettlements return nil, settlement.ErrPeerNoSettlements
} }
return 0, err return nil, err
} }
return totalSent, nil return totalSent, nil
} }
// TotalReceived returns the total amount received from a peer // TotalReceived returns the total amount received from a peer
func (s *Service) TotalReceived(peer swarm.Address) (totalReceived uint64, err error) { func (s *Service) TotalReceived(peer swarm.Address) (totalReceived *big.Int, err error) {
key := totalKey(peer, SettlementReceivedPrefix) key := totalKey(peer, SettlementReceivedPrefix)
err = s.store.Get(key, &totalReceived) err = s.store.Get(key, &totalReceived)
if err != nil { if err != nil {
if errors.Is(err, storage.ErrNotFound) { if errors.Is(err, storage.ErrNotFound) {
return 0, settlement.ErrPeerNoSettlements return nil, settlement.ErrPeerNoSettlements
} }
return 0, err return nil, err
} }
return totalReceived, nil return totalReceived, nil
} }
// AllSettlements returns all stored settlement values for a given type of prefix (sent or received) // SettlementsSent returns all stored sent settlement values for a given type of prefix
func (s *Service) SettlementsSent() (map[string]uint64, error) { func (s *Service) SettlementsSent() (map[string]*big.Int, error) {
sent := make(map[string]uint64) sent := make(map[string]*big.Int)
err := s.store.Iterate(SettlementSentPrefix, func(key, val []byte) (stop bool, err error) { err := s.store.Iterate(SettlementSentPrefix, func(key, val []byte) (stop bool, err error) {
addr, err := totalKeyPeer(key, SettlementSentPrefix) addr, err := totalKeyPeer(key, SettlementSentPrefix)
if err != nil { if err != nil {
return false, fmt.Errorf("parse address from key: %s: %w", string(key), err) return false, fmt.Errorf("parse address from key: %s: %w", string(key), err)
} }
if _, ok := sent[addr.String()]; !ok { if _, ok := sent[addr.String()]; !ok {
var storevalue uint64 var storevalue *big.Int
err = s.store.Get(totalKey(addr, SettlementSentPrefix), &storevalue) err = s.store.Get(totalKey(addr, SettlementSentPrefix), &storevalue)
if err != nil { if err != nil {
return false, fmt.Errorf("get peer %s settlement balance: %w", addr.String(), err) return false, fmt.Errorf("get peer %s settlement balance: %w", addr.String(), err)
...@@ -204,15 +207,16 @@ func (s *Service) SettlementsSent() (map[string]uint64, error) { ...@@ -204,15 +207,16 @@ func (s *Service) SettlementsSent() (map[string]uint64, error) {
return sent, nil return sent, nil
} }
func (s *Service) SettlementsReceived() (map[string]uint64, error) { // SettlementsReceived returns all stored received settlement values for a given type of prefix
received := make(map[string]uint64) func (s *Service) SettlementsReceived() (map[string]*big.Int, error) {
received := make(map[string]*big.Int)
err := s.store.Iterate(SettlementReceivedPrefix, func(key, val []byte) (stop bool, err error) { err := s.store.Iterate(SettlementReceivedPrefix, func(key, val []byte) (stop bool, err error) {
addr, err := totalKeyPeer(key, SettlementReceivedPrefix) addr, err := totalKeyPeer(key, SettlementReceivedPrefix)
if err != nil { if err != nil {
return false, fmt.Errorf("parse address from key: %s: %w", string(key), err) return false, fmt.Errorf("parse address from key: %s: %w", string(key), err)
} }
if _, ok := received[addr.String()]; !ok { if _, ok := received[addr.String()]; !ok {
var storevalue uint64 var storevalue *big.Int
err = s.store.Get(totalKey(addr, SettlementReceivedPrefix), &storevalue) err = s.store.Get(totalKey(addr, SettlementReceivedPrefix), &storevalue)
if err != nil { if err != nil {
return false, fmt.Errorf("get peer %s settlement balance: %w", addr.String(), err) return false, fmt.Errorf("get peer %s settlement balance: %w", addr.String(), err)
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"context" "context"
"io/ioutil" "io/ioutil"
"math/big"
"testing" "testing"
"time" "time"
...@@ -23,7 +24,7 @@ import ( ...@@ -23,7 +24,7 @@ import (
type testObserver struct { type testObserver struct {
called chan struct{} called chan struct{}
peer swarm.Address peer swarm.Address
amount uint64 amount *big.Int
} }
func newTestObserver() *testObserver { func newTestObserver() *testObserver {
...@@ -32,7 +33,7 @@ func newTestObserver() *testObserver { ...@@ -32,7 +33,7 @@ func newTestObserver() *testObserver {
} }
} }
func (t *testObserver) NotifyPayment(peer swarm.Address, amount uint64) error { func (t *testObserver) NotifyPayment(peer swarm.Address, amount *big.Int) error {
close(t.called) close(t.called)
t.peer = peer t.peer = peer
t.amount = amount t.amount = amount
...@@ -59,7 +60,7 @@ func TestPayment(t *testing.T) { ...@@ -59,7 +60,7 @@ func TestPayment(t *testing.T) {
payer := pseudosettle.New(recorder, logger, storePayer) payer := pseudosettle.New(recorder, logger, storePayer)
peerID := swarm.MustParseHexAddress("9ee7add7") peerID := swarm.MustParseHexAddress("9ee7add7")
amount := uint64(10000) amount := big.NewInt(10000)
err := payer.Pay(context.Background(), peerID, amount) err := payer.Pay(context.Background(), peerID, amount)
if err != nil { if err != nil {
...@@ -94,7 +95,7 @@ func TestPayment(t *testing.T) { ...@@ -94,7 +95,7 @@ func TestPayment(t *testing.T) {
} }
sentAmount := messages[0].(*pb.Payment).Amount sentAmount := messages[0].(*pb.Payment).Amount
if sentAmount != amount { if sentAmount != amount.Uint64() {
t.Fatalf("got message with amount %v, want %v", sentAmount, amount) t.Fatalf("got message with amount %v, want %v", sentAmount, amount)
} }
...@@ -104,7 +105,7 @@ func TestPayment(t *testing.T) { ...@@ -104,7 +105,7 @@ func TestPayment(t *testing.T) {
t.Fatal("expected observer to be called") t.Fatal("expected observer to be called")
} }
if observer.amount != amount { if observer.amount.Cmp(amount) != 0 {
t.Fatalf("observer called with wrong amount. got %d, want %d", observer.amount, amount) t.Fatalf("observer called with wrong amount. got %d, want %d", observer.amount, amount)
} }
...@@ -117,7 +118,7 @@ func TestPayment(t *testing.T) { ...@@ -117,7 +118,7 @@ func TestPayment(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if totalSent != sentAmount { if totalSent.Cmp(new(big.Int).SetUint64(sentAmount)) != 0 {
t.Fatalf("stored wrong totalSent. got %d, want %d", totalSent, sentAmount) t.Fatalf("stored wrong totalSent. got %d, want %d", totalSent, sentAmount)
} }
...@@ -126,7 +127,7 @@ func TestPayment(t *testing.T) { ...@@ -126,7 +127,7 @@ func TestPayment(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if totalReceived != sentAmount { if totalReceived.Cmp(new(big.Int).SetUint64(sentAmount)) != 0 {
t.Fatalf("stored wrong totalReceived. got %d, want %d", totalReceived, sentAmount) t.Fatalf("stored wrong totalReceived. got %d, want %d", totalReceived, sentAmount)
} }
} }
...@@ -22,7 +22,7 @@ const chequebookKey = "chequebook" ...@@ -22,7 +22,7 @@ const chequebookKey = "chequebook"
func checkBalance( func checkBalance(
ctx context.Context, ctx context.Context,
logger logging.Logger, logger logging.Logger,
swapInitialDeposit uint64, swapInitialDeposit *big.Int,
swapBackend transaction.Backend, swapBackend transaction.Backend,
chainId int64, chainId int64,
overlayEthAddress common.Address, overlayEthAddress common.Address,
...@@ -47,7 +47,7 @@ func checkBalance( ...@@ -47,7 +47,7 @@ func checkBalance(
return err return err
} }
if balance.Cmp(big.NewInt(int64(swapInitialDeposit))) < 0 { if balance.Cmp(swapInitialDeposit) < 0 {
logger.Warningf("cannot continue until there is sufficient ETH and BZZ available on %x", overlayEthAddress) logger.Warningf("cannot continue until there is sufficient ETH and BZZ available on %x", overlayEthAddress)
if chainId == 5 { if chainId == 5 {
logger.Warningf("on the test network you can get both Goerli ETH and Goerli BZZ from https://faucet.ethswarm.org?address=%x", overlayEthAddress) logger.Warningf("on the test network you can get both Goerli ETH and Goerli BZZ from https://faucet.ethswarm.org?address=%x", overlayEthAddress)
...@@ -70,7 +70,7 @@ func Init( ...@@ -70,7 +70,7 @@ func Init(
chequebookFactory Factory, chequebookFactory Factory,
stateStore storage.StateStorer, stateStore storage.StateStorer,
logger logging.Logger, logger logging.Logger,
swapInitialDeposit uint64, swapInitialDeposit *big.Int,
transactionService transaction.Service, transactionService transaction.Service,
swapBackend transaction.Backend, swapBackend transaction.Backend,
chainId int64, chainId int64,
...@@ -97,7 +97,7 @@ func Init( ...@@ -97,7 +97,7 @@ func Init(
} }
logger.Info("no chequebook found, deploying new one.") logger.Info("no chequebook found, deploying new one.")
if swapInitialDeposit != 0 { if swapInitialDeposit.Cmp(big.NewInt(0)) != 0 {
err = checkBalance(ctx, logger, swapInitialDeposit, swapBackend, chainId, overlayEthAddress, erc20BindingFunc, erc20Address, 20*time.Second, 10) err = checkBalance(ctx, logger, swapInitialDeposit, swapBackend, chainId, overlayEthAddress, erc20BindingFunc, erc20Address, 20*time.Second, 10)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -130,9 +130,9 @@ func Init( ...@@ -130,9 +130,9 @@ func Init(
return nil, err return nil, err
} }
if swapInitialDeposit != 0 { if swapInitialDeposit.Cmp(big.NewInt(0)) != 0 {
logger.Infof("depositing %d token into new chequebook", swapInitialDeposit) logger.Infof("depositing %d token into new chequebook", swapInitialDeposit)
depositHash, err := chequebookService.Deposit(ctx, big.NewInt(int64(swapInitialDeposit))) depositHash, err := chequebookService.Deposit(ctx, swapInitialDeposit)
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -6,6 +6,7 @@ package mock ...@@ -6,6 +6,7 @@ package mock
import ( import (
"context" "context"
"math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -16,14 +17,17 @@ import ( ...@@ -16,14 +17,17 @@ import (
) )
type Service struct { type Service struct {
settlementSentFunc func(swarm.Address) (uint64, error) settlementsSent map[string]*big.Int
settlementRecvFunc func(swarm.Address) (uint64, error) settlementsRecv map[string]*big.Int
settlementsSentFunc func() (map[string]uint64, error) settlementSentFunc func(swarm.Address) (*big.Int, error)
settlementsRecvFunc func() (map[string]uint64, error) settlementRecvFunc func(swarm.Address) (*big.Int, error)
settlementsSentFunc func() (map[string]*big.Int, error)
settlementsRecvFunc func() (map[string]*big.Int, error)
receiveChequeFunc func(context.Context, swarm.Address, *chequebook.SignedCheque) error receiveChequeFunc func(context.Context, swarm.Address, *chequebook.SignedCheque) error
payFunc func(context.Context, swarm.Address, uint64) error payFunc func(context.Context, swarm.Address, *big.Int) error
setNotifyPaymentFunc settlement.NotifyPaymentFunc setNotifyPaymentFunc settlement.NotifyPaymentFunc
handshakeFunc func(swarm.Address, common.Address) error handshakeFunc func(swarm.Address, common.Address) error
lastSentChequeFunc func(swarm.Address) (*chequebook.SignedCheque, error) lastSentChequeFunc func(swarm.Address) (*chequebook.SignedCheque, error)
...@@ -37,26 +41,26 @@ type Service struct { ...@@ -37,26 +41,26 @@ type Service struct {
} }
// WithsettlementFunc sets the mock settlement function // WithsettlementFunc sets the mock settlement function
func WithSettlementSentFunc(f func(swarm.Address) (uint64, error)) Option { func WithSettlementSentFunc(f func(swarm.Address) (*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.settlementSentFunc = f s.settlementSentFunc = f
}) })
} }
func WithSettlementRecvFunc(f func(swarm.Address) (uint64, error)) Option { func WithSettlementRecvFunc(f func(swarm.Address) (*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.settlementRecvFunc = f s.settlementRecvFunc = f
}) })
} }
// WithsettlementsFunc sets the mock settlements function // WithsettlementsFunc sets the mock settlements function
func WithSettlementsSentFunc(f func() (map[string]uint64, error)) Option { func WithSettlementsSentFunc(f func() (map[string]*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.settlementsSentFunc = f s.settlementsSentFunc = f
}) })
} }
func WithSettlementsRecvFunc(f func() (map[string]uint64, error)) Option { func WithSettlementsRecvFunc(f func() (map[string]*big.Int, error)) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.settlementsRecvFunc = f s.settlementsRecvFunc = f
}) })
...@@ -68,7 +72,7 @@ func WithReceiveChequeFunc(f func(context.Context, swarm.Address, *chequebook.Si ...@@ -68,7 +72,7 @@ func WithReceiveChequeFunc(f func(context.Context, swarm.Address, *chequebook.Si
}) })
} }
func WithPayFunc(f func(context.Context, swarm.Address, uint64) error) Option { func WithPayFunc(f func(context.Context, swarm.Address, *big.Int) error) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.payFunc = f s.payFunc = f
}) })
...@@ -126,6 +130,8 @@ func WithCashoutStatusFunc(f func(ctx context.Context, peer swarm.Address) (*che ...@@ -126,6 +130,8 @@ func WithCashoutStatusFunc(f func(ctx context.Context, peer swarm.Address) (*che
// New creates the mock swap implementation // New creates the mock swap implementation
func New(opts ...Option) settlement.Interface { func New(opts ...Option) settlement.Interface {
mock := new(Service) mock := new(Service)
mock.settlementsSent = make(map[string]*big.Int)
mock.settlementsRecv = make(map[string]*big.Int)
for _, o := range opts { for _, o := range opts {
o.apply(mock) o.apply(mock)
} }
...@@ -149,10 +155,15 @@ func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque ...@@ -149,10 +155,15 @@ func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque
} }
// Pay is the mock Pay function of swap. // Pay is the mock Pay function of swap.
func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) error { func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int) error {
if s.payFunc != nil { if s.payFunc != nil {
return s.payFunc(ctx, peer, amount) return s.payFunc(ctx, peer, amount)
} }
if settlement, ok := s.settlementsSent[peer.String()]; ok {
s.settlementsSent[peer.String()] = big.NewInt(0).Add(settlement, amount)
} else {
s.settlementsSent[peer.String()] = amount
}
return nil return nil
} }
...@@ -163,37 +174,41 @@ func (s *Service) SetNotifyPaymentFunc(f settlement.NotifyPaymentFunc) { ...@@ -163,37 +174,41 @@ func (s *Service) SetNotifyPaymentFunc(f settlement.NotifyPaymentFunc) {
} }
// TotalSent is the mock TotalSent function of swap. // TotalSent is the mock TotalSent function of swap.
func (s *Service) TotalSent(peer swarm.Address) (totalSent uint64, err error) { func (s *Service) TotalSent(peer swarm.Address) (totalSent *big.Int, err error) {
if s.settlementSentFunc != nil { if s.settlementSentFunc != nil {
return s.settlementSentFunc(peer) return s.settlementSentFunc(peer)
} }
return 0, nil if v, ok := s.settlementsSent[peer.String()]; ok {
return v, nil
}
return big.NewInt(0), nil
} }
// TotalReceived is the mock TotalReceived function of swap. // TotalReceived is the mock TotalReceived function of swap.
func (s *Service) TotalReceived(peer swarm.Address) (totalReceived uint64, err error) { func (s *Service) TotalReceived(peer swarm.Address) (totalReceived *big.Int, err error) {
if s.settlementRecvFunc != nil { if s.settlementRecvFunc != nil {
return s.settlementRecvFunc(peer) return s.settlementRecvFunc(peer)
} }
return 0, nil if v, ok := s.settlementsRecv[peer.String()]; ok {
return v, nil
}
return big.NewInt(0), nil
} }
// SettlementsSent is the mock SettlementsSent function of swap. // SettlementsSent is the mock SettlementsSent function of swap.
func (s *Service) SettlementsSent() (map[string]uint64, error) { func (s *Service) SettlementsSent() (map[string]*big.Int, error) {
if s.settlementsSentFunc != nil { if s.settlementsSentFunc != nil {
return s.settlementsSentFunc() return s.settlementsSentFunc()
} }
result := make(map[string]uint64) return s.settlementsSent, nil
return result, nil
} }
// SettlementsReceived is the mock SettlementsReceived function of swap. // SettlementsReceived is the mock SettlementsReceived function of swap.
func (s *Service) SettlementsReceived() (map[string]uint64, error) { func (s *Service) SettlementsReceived() (map[string]*big.Int, error) {
if s.settlementsRecvFunc != nil { if s.settlementsRecvFunc != nil {
return s.settlementsRecvFunc() return s.settlementsRecvFunc()
} }
result := make(map[string]uint64) return s.settlementsRecv, nil
return result, nil
} }
// Handshake is called by the swap protocol when a handshake is received. // Handshake is called by the swap protocol when a handshake is received.
......
...@@ -102,11 +102,11 @@ func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque ...@@ -102,11 +102,11 @@ func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque
s.metrics.TotalReceived.Add(float64(amount.Uint64())) s.metrics.TotalReceived.Add(float64(amount.Uint64()))
return s.notifyPaymentFunc(peer, amount.Uint64()) return s.notifyPaymentFunc(peer, amount)
} }
// Pay initiates a payment to the given peer // Pay initiates a payment to the given peer
func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) error { func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int) error {
beneficiary, known, err := s.addressbook.Beneficiary(peer) beneficiary, known, err := s.addressbook.Beneficiary(peer)
if err != nil { if err != nil {
return err return err
...@@ -119,7 +119,7 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er ...@@ -119,7 +119,7 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er
} }
return ErrUnknownBeneficary return ErrUnknownBeneficary
} }
balance, err := s.chequebook.Issue(ctx, beneficiary, big.NewInt(int64(amount)), func(signedCheque *chequebook.SignedCheque) error { balance, err := s.chequebook.Issue(ctx, beneficiary, amount, func(signedCheque *chequebook.SignedCheque) error {
return s.proto.EmitCheque(ctx, peer, signedCheque) return s.proto.EmitCheque(ctx, peer, signedCheque)
}) })
if err != nil { if err != nil {
...@@ -127,7 +127,8 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er ...@@ -127,7 +127,8 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount uint64) er
} }
bal, _ := big.NewFloat(0).SetInt(balance).Float64() bal, _ := big.NewFloat(0).SetInt(balance).Float64()
s.metrics.AvailableBalance.Set(bal) s.metrics.AvailableBalance.Set(bal)
s.metrics.TotalSent.Add(float64(amount)) amountFloat, _ := big.NewFloat(0).SetInt(amount).Float64()
s.metrics.TotalSent.Add(amountFloat)
return nil return nil
} }
...@@ -137,47 +138,47 @@ func (s *Service) SetNotifyPaymentFunc(notifyPaymentFunc settlement.NotifyPaymen ...@@ -137,47 +138,47 @@ func (s *Service) SetNotifyPaymentFunc(notifyPaymentFunc settlement.NotifyPaymen
} }
// TotalSent returns the total amount sent to a peer // TotalSent returns the total amount sent to a peer
func (s *Service) TotalSent(peer swarm.Address) (totalSent uint64, err error) { func (s *Service) TotalSent(peer swarm.Address) (totalSent *big.Int, err error) {
beneficiary, known, err := s.addressbook.Beneficiary(peer) beneficiary, known, err := s.addressbook.Beneficiary(peer)
if err != nil { if err != nil {
return 0, err return nil, err
} }
if !known { if !known {
return 0, settlement.ErrPeerNoSettlements return nil, settlement.ErrPeerNoSettlements
} }
cheque, err := s.chequebook.LastCheque(beneficiary) cheque, err := s.chequebook.LastCheque(beneficiary)
if err != nil { if err != nil {
if err == chequebook.ErrNoCheque { if err == chequebook.ErrNoCheque {
return 0, settlement.ErrPeerNoSettlements return nil, settlement.ErrPeerNoSettlements
} }
return 0, err return nil, err
} }
return cheque.CumulativePayout.Uint64(), nil return cheque.CumulativePayout, nil
} }
// TotalReceived returns the total amount received from a peer // TotalReceived returns the total amount received from a peer
func (s *Service) TotalReceived(peer swarm.Address) (totalReceived uint64, err error) { func (s *Service) TotalReceived(peer swarm.Address) (totalReceived *big.Int, err error) {
chequebookAddress, known, err := s.addressbook.Chequebook(peer) chequebookAddress, known, err := s.addressbook.Chequebook(peer)
if err != nil { if err != nil {
return 0, err return nil, err
} }
if !known { if !known {
return 0, settlement.ErrPeerNoSettlements return nil, settlement.ErrPeerNoSettlements
} }
cheque, err := s.chequeStore.LastCheque(chequebookAddress) cheque, err := s.chequeStore.LastCheque(chequebookAddress)
if err != nil { if err != nil {
if err == chequebook.ErrNoCheque { if err == chequebook.ErrNoCheque {
return 0, settlement.ErrPeerNoSettlements return nil, settlement.ErrPeerNoSettlements
} }
return 0, err return nil, err
} }
return cheque.CumulativePayout.Uint64(), nil return cheque.CumulativePayout, nil
} }
// SettlementsSent returns sent settlements for each individual known peer // SettlementsSent returns sent settlements for each individual known peer
func (s *Service) SettlementsSent() (map[string]uint64, error) { func (s *Service) SettlementsSent() (map[string]*big.Int, error) {
result := make(map[string]uint64) result := make(map[string]*big.Int)
cheques, err := s.chequebook.LastCheques() cheques, err := s.chequebook.LastCheques()
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -191,15 +192,15 @@ func (s *Service) SettlementsSent() (map[string]uint64, error) { ...@@ -191,15 +192,15 @@ func (s *Service) SettlementsSent() (map[string]uint64, error) {
if !known { if !known {
continue continue
} }
result[peer.String()] = cheque.CumulativePayout.Uint64() result[peer.String()] = cheque.CumulativePayout
} }
return result, nil return result, nil
} }
// SettlementsReceived returns received settlements for each individual known peer. // SettlementsReceived returns received settlements for each individual known peer.
func (s *Service) SettlementsReceived() (map[string]uint64, error) { func (s *Service) SettlementsReceived() (map[string]*big.Int, error) {
result := make(map[string]uint64) result := make(map[string]*big.Int)
cheques, err := s.chequeStore.LastCheques() cheques, err := s.chequeStore.LastCheques()
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -213,7 +214,7 @@ func (s *Service) SettlementsReceived() (map[string]uint64, error) { ...@@ -213,7 +214,7 @@ func (s *Service) SettlementsReceived() (map[string]uint64, error) {
if !known { if !known {
continue continue
} }
result[peer.String()] = cheque.CumulativePayout.Uint64() result[peer.String()] = cheque.CumulativePayout
} }
return result, err return result, err
} }
......
...@@ -37,10 +37,10 @@ func (m *swapProtocolMock) EmitCheque(ctx context.Context, peer swarm.Address, c ...@@ -37,10 +37,10 @@ func (m *swapProtocolMock) EmitCheque(ctx context.Context, peer swarm.Address, c
type testObserver struct { type testObserver struct {
called bool called bool
peer swarm.Address peer swarm.Address
amount uint64 amount *big.Int
} }
func (t *testObserver) NotifyPayment(peer swarm.Address, amount uint64) error { func (t *testObserver) NotifyPayment(peer swarm.Address, amount *big.Int) error {
t.called = true t.called = true
t.peer = peer t.peer = peer
t.amount = amount t.amount = amount
...@@ -155,7 +155,7 @@ func TestReceiveCheque(t *testing.T) { ...@@ -155,7 +155,7 @@ func TestReceiveCheque(t *testing.T) {
t.Fatal("expected observer to be called") t.Fatal("expected observer to be called")
} }
if observer.amount != amount.Uint64() { if observer.amount.Cmp(amount) != 0 {
t.Fatalf("observer called with wrong amount. got %d, want %d", observer.amount, amount) t.Fatalf("observer called with wrong amount. got %d, want %d", observer.amount, amount)
} }
...@@ -278,7 +278,7 @@ func TestPay(t *testing.T) { ...@@ -278,7 +278,7 @@ func TestPay(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
store := mockstore.NewStateStore() store := mockstore.NewStateStore()
amount := uint64(50) amount := big.NewInt(50)
beneficiary := common.HexToAddress("0xcd") beneficiary := common.HexToAddress("0xcd")
var cheque chequebook.SignedCheque var cheque chequebook.SignedCheque
...@@ -289,7 +289,7 @@ func TestPay(t *testing.T) { ...@@ -289,7 +289,7 @@ func TestPay(t *testing.T) {
if b != beneficiary { if b != beneficiary {
t.Fatalf("issuing cheque for wrong beneficiary. wanted %v, got %v", beneficiary, b) t.Fatalf("issuing cheque for wrong beneficiary. wanted %v, got %v", beneficiary, b)
} }
if a.Uint64() != amount { if a.Cmp(amount) != 0 {
t.Fatalf("issuing cheque with wrong amount. wanted %d, got %d", amount, a) t.Fatalf("issuing cheque with wrong amount. wanted %d, got %d", amount, a)
} }
chequebookCalled = true chequebookCalled = true
...@@ -349,7 +349,7 @@ func TestPayIssueError(t *testing.T) { ...@@ -349,7 +349,7 @@ func TestPayIssueError(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
store := mockstore.NewStateStore() store := mockstore.NewStateStore()
amount := uint64(50) amount := big.NewInt(50)
beneficiary := common.HexToAddress("0xcd") beneficiary := common.HexToAddress("0xcd")
peer := swarm.MustParseHexAddress("abcd") peer := swarm.MustParseHexAddress("abcd")
...@@ -392,7 +392,7 @@ func TestPayUnknownBeneficiary(t *testing.T) { ...@@ -392,7 +392,7 @@ func TestPayUnknownBeneficiary(t *testing.T) {
logger := logging.New(ioutil.Discard, 0) logger := logging.New(ioutil.Discard, 0)
store := mockstore.NewStateStore() store := mockstore.NewStateStore()
amount := uint64(50) amount := big.NewInt(50)
peer := swarm.MustParseHexAddress("abcd") peer := swarm.MustParseHexAddress("abcd")
networkID := uint64(1) networkID := uint64(1)
addressbook := &addressbookMock{ addressbook := &addressbookMock{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment