Commit c1e87cef authored by Ralph Pichler's avatar Ralph Pichler Committed by GitHub

feat: time based settlements (#1711)

parent 4b730a6f
...@@ -64,7 +64,7 @@ jobs: ...@@ -64,7 +64,7 @@ jobs:
run: | run: |
echo -e "127.0.0.10\tregistry.localhost" | sudo tee -a /etc/hosts echo -e "127.0.0.10\tregistry.localhost" | sudo tee -a /etc/hosts
for ((i=0; i<REPLICA; i++)); do echo -e "127.0.1.$((i+1))\tbee-${i}.localhost bee-${i}-debug.localhost"; done | sudo tee -a /etc/hosts for ((i=0; i<REPLICA; i++)); do echo -e "127.0.1.$((i+1))\tbee-${i}.localhost bee-${i}-debug.localhost"; done | sudo tee -a /etc/hosts
timeout 30m ./beeinfra.sh install --local -r "${REPLICA}" --bootnode /dnsaddr/localhost --geth --k3s --pay-threshold 2000000000000 --postage timeout 30m ./beeinfra.sh install --local -r "${REPLICA}" --bootnode /dnsaddr/localhost --geth --k3s --pay-threshold 1500000000000 --postage
- name: Test pingpong - name: Test pingpong
id: pingpong-1 id: pingpong-1
run: until ./beekeeper check pingpong --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"; do echo "waiting for pingpong..."; sleep .3; done run: until ./beekeeper check pingpong --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"; do echo "waiting for pingpong..."; sleep .3; done
...@@ -73,7 +73,15 @@ jobs: ...@@ -73,7 +73,15 @@ jobs:
run: ./beekeeper check fullconnectivity --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" run: ./beekeeper check fullconnectivity --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"
- name: Test settlements - name: Test settlements
id: settlements-1 id: settlements-1
run: ./beekeeper check settlements --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --upload-node-count "${REPLICA}" -t 2000000000000 run: |
./beekeeper check settlements --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --upload-node-count "${REPLICA}" -t 1500000000000
sleep 2
- name: Test pss
id: pss
run: ./beekeeper check pss --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --timeout 5m
- name: Test soc
id: soc
run: ./beekeeper check soc --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"
- name: Test pushsync (chunks) - name: Test pushsync (chunks)
id: pushsync-chunks-1 id: pushsync-chunks-1
run: ./beekeeper check pushsync --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --upload-node-count "${REPLICA}" --chunks-per-node 3 --upload-chunks --retry-delay 15s run: ./beekeeper check pushsync --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --upload-node-count "${REPLICA}" --chunks-per-node 3 --upload-chunks --retry-delay 15s
...@@ -83,12 +91,6 @@ jobs: ...@@ -83,12 +91,6 @@ jobs:
- name: Test manifest - name: Test manifest
id: manifest-1 id: manifest-1
run: ./beekeeper check manifest --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" run: ./beekeeper check manifest --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"
- name: Test pss
id: pss
run: ./beekeeper check pss --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --timeout 5m
- name: Test soc
id: soc
run: ./beekeeper check soc --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"
- name: Destroy the cluster - name: Destroy the cluster
run: | run: |
./beeinfra.sh uninstall ./beeinfra.sh uninstall
...@@ -101,7 +103,7 @@ jobs: ...@@ -101,7 +103,7 @@ jobs:
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
- name: Set testing cluster (Node connection and clef enabled) - name: Set testing cluster (Node connection and clef enabled)
run: | run: |
timeout 30m ./beeinfra.sh install --local -r "${REPLICA}" --geth --clef --k3s --pay-threshold 2000000000000 --postage timeout 30m ./beeinfra.sh install --local -r "${REPLICA}" --geth --clef --k3s --pay-threshold 1500000000000 --postage
- name: Test pingpong - name: Test pingpong
id: pingpong-2 id: pingpong-2
run: until ./beekeeper check pingpong --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"; do echo "waiting for pingpong..."; sleep .3; done run: until ./beekeeper check pingpong --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"; do echo "waiting for pingpong..."; sleep .3; done
...@@ -110,7 +112,7 @@ jobs: ...@@ -110,7 +112,7 @@ jobs:
run: ./beekeeper check fullconnectivity --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" run: ./beekeeper check fullconnectivity --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"
- name: Test settlements - name: Test settlements
id: settlements-2 id: settlements-2
run: ./beekeeper check settlements --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --upload-node-count "${REPLICA}" -t 2000000000000 run: ./beekeeper check settlements --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" --upload-node-count "${REPLICA}" -t 1500000000000
- name: Destroy the cluster - name: Destroy the cluster
run: | run: |
./beeinfra.sh uninstall ./beeinfra.sh uninstall
...@@ -126,7 +128,7 @@ jobs: ...@@ -126,7 +128,7 @@ jobs:
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
- name: Set testing cluster (storage incentives setup) - name: Set testing cluster (storage incentives setup)
run: | run: |
timeout 10m ./beeinfra.sh install --local -r "${REPLICA}" --geth --k3s --pay-threshold 2000000000000 --postage --db-capacity 100 timeout 10m ./beeinfra.sh install --local -r "${REPLICA}" --geth --k3s --pay-threshold 1500000000000 --postage --db-capacity 100
- name: Test gc - name: Test gc
id: gc-chunk-1 id: gc-chunk-1
run: ./beekeeper check gc --cache-capacity 100 --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}" run: ./beekeeper check gc --cache-capacity 100 --api-scheme http --debug-api-scheme http --disable-namespace --debug-api-domain localhost --api-domain localhost --node-count "${REPLICA}"
......
...@@ -218,7 +218,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) { ...@@ -218,7 +218,7 @@ func (c *command) setAllFlags(cmd *cobra.Command) {
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().String(optionNamePaymentThreshold, "10000000000000", "threshold in BZZ where you expect to get paid from your peers") cmd.Flags().String(optionNamePaymentThreshold, "10000000000000", "threshold in BZZ where you expect to get paid from your peers")
cmd.Flags().String(optionNamePaymentTolerance, "50000000000000", "excess debt above payment threshold in BZZ where you disconnect from your peer") cmd.Flags().String(optionNamePaymentTolerance, "10000000000000", "excess debt above payment threshold in BZZ where you disconnect from your peer")
cmd.Flags().String(optionNamePaymentEarly, "1000000000000", "amount in BZZ below the peers payment threshold when we initiate settlement") cmd.Flags().String(optionNamePaymentEarly, "1000000000000", "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")
......
...@@ -52,8 +52,8 @@ password-file: /var/lib/bee/password ...@@ -52,8 +52,8 @@ password-file: /var/lib/bee/password
# payment-early: 1000000000000 # payment-early: 1000000000000
## threshold in BZZ where you expect to get paid from your peers (default 10000000000000) ## threshold in BZZ where you expect to get paid from your peers (default 10000000000000)
# payment-threshold: 10000000000000 # payment-threshold: 10000000000000
## excess debt above payment threshold in BZZ where you disconnect from your peer (default 50000000000000) ## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000000000000)
# payment-tolerance: 50000000000000 # payment-tolerance: 10000000000000
## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url ## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url
# resolver-options: [] # resolver-options: []
## whether we want the node to start with no listen addresses for p2p ## whether we want the node to start with no listen addresses for p2p
......
...@@ -55,12 +55,12 @@ BEE_CLEF_SIGNER_ENABLE=true ...@@ -55,12 +55,12 @@ BEE_CLEF_SIGNER_ENABLE=true
# BEE_PASSWORD= # BEE_PASSWORD=
## path to a file that contains password for decrypting keys ## path to a file that contains password for decrypting keys
# BEE_PASSWORD_FILE= # BEE_PASSWORD_FILE=
## amount in BZZ below the peers payment threshold when we initiate settlement (default 10000) ## amount in BZZ below the peers payment threshold when we initiate settlement (default 1000000000000)
# BEE_PAYMENT_EARLY=10000 # BEE_PAYMENT_EARLY=1000000000000
## threshold in BZZ where you expect to get paid from your peers (default 100000) ## threshold in BZZ where you expect to get paid from your peers (default 10000000000000)
# BEE_PAYMENT_THRESHOLD=100000 # BEE_PAYMENT_THRESHOLD=10000000000000
## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000) ## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000000000000)
# BEE_PAYMENT_TOLERANCE=10000 # BEE_PAYMENT_TOLERANCE=10000000000000
## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url ## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url
# BEE_RESOLVER_OPTIONS=[] # BEE_RESOLVER_OPTIONS=[]
## whether we want the node to start with no listen addresses for p2p ## whether we want the node to start with no listen addresses for p2p
......
...@@ -52,8 +52,8 @@ password-file: /usr/local/var/lib/swarm-bee/password ...@@ -52,8 +52,8 @@ password-file: /usr/local/var/lib/swarm-bee/password
# payment-early: 1000000000000 # payment-early: 1000000000000
## threshold in BZZ where you expect to get paid from your peers (default 10000000000000) ## threshold in BZZ where you expect to get paid from your peers (default 10000000000000)
# payment-threshold: 10000000000000 # payment-threshold: 10000000000000
## excess debt above payment threshold in BZZ where you disconnect from your peer (default 50000000000000) ## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000000000000)
# payment-tolerance: 50000000000000 # payment-tolerance: 10000000000000
## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url ## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url
# resolver-options: [] # resolver-options: []
## whether we want the node to start with no listen addresses for p2p ## whether we want the node to start with no listen addresses for p2p
......
...@@ -38,12 +38,12 @@ data-dir: ./data ...@@ -38,12 +38,12 @@ data-dir: ./data
# password: "" # password: ""
## path to a file that contains password for decrypting keys ## path to a file that contains password for decrypting keys
password-file: ./password password-file: ./password
## amount in BZZ below the peers payment threshold when we initiate settlement (default 10000) ## amount in BZZ below the peers payment threshold when we initiate settlement (default 1000000000000)
# payment-early: 10000 # payment-early: 1000000000000
## threshold in BZZ where you expect to get paid from your peers (default 100000) ## threshold in BZZ where you expect to get paid from your peers (default 10000000000000)
# payment-threshold: 100000 # payment-threshold: 10000000000000
## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000) ## excess debt above payment threshold in BZZ where you disconnect from your peer (default 10000000000000)
# payment-tolerance: 10000 # payment-tolerance: 10000000000000
## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url ## ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url
# resolver-options: [] # resolver-options: []
## whether we want the node to start with no listen addresses for p2p ## whether we want the node to start with no listen addresses for p2p
......
This diff is collapsed.
This diff is collapsed.
package accounting
import (
"time"
"github.com/ethersphere/bee/pkg/swarm"
)
func (s *Accounting) SetTimeNow(f func() time.Time) {
s.timeNow = f
}
func (s *Accounting) SetTime(k int64) {
s.SetTimeNow(func() time.Time {
return time.Unix(k, 0)
})
}
func (a *Accounting) IsPaymentOngoing(peer swarm.Address) bool {
return a.getAccountingPeer(peer).paymentOngoing
}
...@@ -22,8 +22,9 @@ type Service struct { ...@@ -22,8 +22,9 @@ type Service struct {
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 prepareDebitFunc func(peer swarm.Address, price uint64) accounting.Action
balanceFunc func(swarm.Address) (*big.Int, error) balanceFunc func(swarm.Address) (*big.Int, error)
shadowBalanceFunc func(swarm.Address) (*big.Int, error)
balancesFunc func() (map[string]*big.Int, error) balancesFunc func() (map[string]*big.Int, error)
compensatedBalanceFunc func(swarm.Address) (*big.Int, error) compensatedBalanceFunc func(swarm.Address) (*big.Int, error)
compensatedBalancesFunc func() (map[string]*big.Int, error) compensatedBalancesFunc func() (map[string]*big.Int, error)
...@@ -31,6 +32,13 @@ type Service struct { ...@@ -31,6 +32,13 @@ type Service struct {
balanceSurplusFunc func(swarm.Address) (*big.Int, error) balanceSurplusFunc func(swarm.Address) (*big.Int, error)
} }
type debitAction struct {
accounting *Service
price *big.Int
peer swarm.Address
applied bool
}
// WithReserveFunc sets the mock Reserve function // WithReserveFunc sets the mock Reserve function
func WithReserveFunc(f func(ctx context.Context, peer swarm.Address, price uint64) error) Option { func WithReserveFunc(f func(ctx context.Context, peer swarm.Address, price uint64) error) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
...@@ -53,9 +61,9 @@ func WithCreditFunc(f func(peer swarm.Address, price uint64) error) Option { ...@@ -53,9 +61,9 @@ func WithCreditFunc(f func(peer swarm.Address, price uint64) error) Option {
} }
// WithDebitFunc sets the mock Debit function // WithDebitFunc sets the mock Debit function
func WithDebitFunc(f func(peer swarm.Address, price uint64) error) Option { func WithPrepareDebitFunc(f func(peer swarm.Address, price uint64) accounting.Action) Option {
return optionFunc(func(s *Service) { return optionFunc(func(s *Service) {
s.debitFunc = f s.prepareDebitFunc = f
}) })
} }
...@@ -136,21 +144,36 @@ func (s *Service) Credit(peer swarm.Address, price uint64) error { ...@@ -136,21 +144,36 @@ func (s *Service) Credit(peer swarm.Address, price uint64) error {
} }
// Debit is the mock function wrapper that calls the set implementation // Debit is the mock function wrapper that calls the set implementation
func (s *Service) Debit(peer swarm.Address, price uint64) error { func (s *Service) PrepareDebit(peer swarm.Address, price uint64) accounting.Action {
if s.debitFunc != nil { if s.prepareDebitFunc != nil {
return s.debitFunc(peer, price) return s.prepareDebitFunc(peer, price)
} }
s.lock.Lock()
defer s.lock.Unlock()
if bal, ok := s.balances[peer.String()]; ok { bigPrice := new(big.Int).SetUint64(price)
s.balances[peer.String()] = new(big.Int).Add(bal, new(big.Int).SetUint64(price)) return &debitAction{
accounting: s,
price: bigPrice,
peer: peer,
applied: false,
}
}
func (a *debitAction) Apply() error {
a.accounting.lock.Lock()
defer a.accounting.lock.Unlock()
if bal, ok := a.accounting.balances[a.peer.String()]; ok {
a.accounting.balances[a.peer.String()] = new(big.Int).Add(bal, new(big.Int).Set(a.price))
} else { } else {
s.balances[peer.String()] = new(big.Int).SetUint64(price) a.accounting.balances[a.peer.String()] = new(big.Int).Set(a.price)
} }
return nil return nil
} }
func (a *debitAction) Cleanup() {}
// 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) (*big.Int, error) { func (s *Service) Balance(peer swarm.Address) (*big.Int, error) {
if s.balanceFunc != nil { if s.balanceFunc != nil {
...@@ -165,6 +188,19 @@ func (s *Service) Balance(peer swarm.Address) (*big.Int, error) { ...@@ -165,6 +188,19 @@ func (s *Service) Balance(peer swarm.Address) (*big.Int, error) {
} }
} }
func (s *Service) ShadowBalance(peer swarm.Address) (*big.Int, error) {
if s.shadowBalanceFunc != nil {
return s.shadowBalanceFunc(peer)
}
s.lock.Lock()
defer s.lock.Unlock()
if bal, ok := s.balances[peer.String()]; ok {
return new(big.Int).Neg(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]*big.Int, error) { func (s *Service) Balances() (map[string]*big.Int, error) {
if s.balancesFunc != nil { if s.balancesFunc != nil {
......
...@@ -44,10 +44,10 @@ type Service struct { ...@@ -44,10 +44,10 @@ type Service struct {
tracer *tracing.Tracer tracer *tracing.Tracer
tags *tags.Tags tags *tags.Tags
accounting accounting.Interface accounting accounting.Interface
settlement settlement.Interface pseudosettle settlement.Interface
chequebookEnabled bool chequebookEnabled bool
chequebook chequebook.Service chequebook chequebook.Service
swap swap.ApiInterface swap swap.Interface
batchStore postage.Storer batchStore postage.Storer
corsAllowedOrigins []string corsAllowedOrigins []string
metricsRegistry *prometheus.Registry metricsRegistry *prometheus.Registry
...@@ -80,19 +80,19 @@ func New(overlay swarm.Address, publicKey, pssPublicKey ecdsa.PublicKey, ethereu ...@@ -80,19 +80,19 @@ func New(overlay swarm.Address, publicKey, pssPublicKey ecdsa.PublicKey, ethereu
// Configure injects required dependencies and configuration parameters and // Configure injects required dependencies and configuration parameters and
// constructs HTTP routes that depend on them. It is intended and safe to call // constructs HTTP routes that depend on them. It is intended and safe to call
// this method only once. // this method only once.
func (s *Service) Configure(p2p p2p.DebugService, pingpong pingpong.Interface, topologyDriver topology.Driver, lightNodes *lightnode.Container, storer storage.Storer, tags *tags.Tags, accounting accounting.Interface, settlement settlement.Interface, chequebookEnabled bool, swap swap.ApiInterface, chequebook chequebook.Service, batchStore postage.Storer) { func (s *Service) Configure(p2p p2p.DebugService, pingpong pingpong.Interface, topologyDriver topology.Driver, lightNodes *lightnode.Container, storer storage.Storer, tags *tags.Tags, accounting accounting.Interface, pseudosettle settlement.Interface, chequebookEnabled bool, swap swap.Interface, chequebook chequebook.Service, batchStore postage.Storer) {
s.p2p = p2p s.p2p = p2p
s.pingpong = pingpong s.pingpong = pingpong
s.topologyDriver = topologyDriver s.topologyDriver = topologyDriver
s.storer = storer s.storer = storer
s.tags = tags s.tags = tags
s.accounting = accounting s.accounting = accounting
s.settlement = settlement
s.chequebookEnabled = chequebookEnabled s.chequebookEnabled = chequebookEnabled
s.chequebook = chequebook s.chequebook = chequebook
s.swap = swap s.swap = swap
s.lightNodes = lightNodes s.lightNodes = lightNodes
s.batchStore = batchStore s.batchStore = batchStore
s.pseudosettle = pseudosettle
s.setRouter(s.newRouter()) s.setRouter(s.newRouter())
} }
......
...@@ -65,7 +65,7 @@ func newTestServer(t *testing.T, o testServerOptions) *testServer { ...@@ -65,7 +65,7 @@ func newTestServer(t *testing.T, o testServerOptions) *testServer {
acc := accountingmock.NewAccounting(o.AccountingOpts...) acc := accountingmock.NewAccounting(o.AccountingOpts...)
settlement := swapmock.New(o.SettlementOpts...) settlement := swapmock.New(o.SettlementOpts...)
chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...) chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...)
swapserv := swapmock.NewApiInterface(o.SwapOpts...) swapserv := swapmock.New(o.SwapOpts...)
ln := lightnode.NewContainer() ln := lightnode.NewContainer()
s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, o.CORSAllowedOrigins) s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, o.CORSAllowedOrigins)
s.Configure(o.P2P, o.Pingpong, topologyDriver, ln, o.Storer, o.Tags, acc, settlement, true, swapserv, chequebook, o.BatchStore) s.Configure(o.P2P, o.Pingpong, topologyDriver, ln, o.Storer, o.Tags, acc, settlement, true, swapserv, chequebook, o.BatchStore)
...@@ -132,7 +132,7 @@ func TestServer_Configure(t *testing.T) { ...@@ -132,7 +132,7 @@ func TestServer_Configure(t *testing.T) {
acc := accountingmock.NewAccounting(o.AccountingOpts...) acc := accountingmock.NewAccounting(o.AccountingOpts...)
settlement := swapmock.New(o.SettlementOpts...) settlement := swapmock.New(o.SettlementOpts...)
chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...) chequebook := chequebookmock.NewChequebook(o.ChequebookOpts...)
swapserv := swapmock.NewApiInterface(o.SwapOpts...) swapserv := swapmock.New(o.SwapOpts...)
ln := lightnode.NewContainer() ln := lightnode.NewContainer()
s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, nil) s := debugapi.New(o.Overlay, o.PublicKey, o.PSSPublicKey, o.EthereumAddress, logging.New(ioutil.Discard, 0), nil, nil)
ts := httptest.NewServer(s) ts := httptest.NewServer(s)
......
...@@ -125,15 +125,18 @@ func (s *Service) newRouter() *mux.Router { ...@@ -125,15 +125,18 @@ func (s *Service) newRouter() *mux.Router {
"GET": http.HandlerFunc(s.peerBalanceHandler), "GET": http.HandlerFunc(s.peerBalanceHandler),
}) })
router.Handle("/settlements", jsonhttp.MethodHandler{ router.Handle("/timesettlements", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.settlementsHandler), "GET": http.HandlerFunc(s.settlementsHandlerPseudosettle),
})
router.Handle("/settlements/{peer}", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.peerSettlementsHandler),
}) })
if s.chequebookEnabled { if s.chequebookEnabled {
router.Handle("/settlements", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.settlementsHandler),
})
router.Handle("/settlements/{peer}", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.peerSettlementsHandler),
})
router.Handle("/chequebook/balance", jsonhttp.MethodHandler{ router.Handle("/chequebook/balance", jsonhttp.MethodHandler{
"GET": http.HandlerFunc(s.chequebookBalanceHandler), "GET": http.HandlerFunc(s.chequebookBalanceHandler),
}) })
......
...@@ -34,14 +34,14 @@ type settlementsResponse struct { ...@@ -34,14 +34,14 @@ type settlementsResponse struct {
func (s *Service) settlementsHandler(w http.ResponseWriter, r *http.Request) { func (s *Service) settlementsHandler(w http.ResponseWriter, r *http.Request) {
settlementsSent, err := s.settlement.SettlementsSent() settlementsSent, err := s.swap.SettlementsSent()
if err != nil { if err != nil {
jsonhttp.InternalServerError(w, errCantSettlements) jsonhttp.InternalServerError(w, errCantSettlements)
s.logger.Debugf("debug api: sent settlements: %v", err) s.logger.Debugf("debug api: sent settlements: %v", err)
s.logger.Error("debug api: can not get sent settlements") s.logger.Error("debug api: can not get sent settlements")
return return
} }
settlementsReceived, err := s.settlement.SettlementsReceived() settlementsReceived, err := s.swap.SettlementsReceived()
if err != nil { if err != nil {
jsonhttp.InternalServerError(w, errCantSettlements) jsonhttp.InternalServerError(w, errCantSettlements)
s.logger.Debugf("debug api: received settlements: %v", err) s.logger.Debugf("debug api: received settlements: %v", err)
...@@ -100,7 +100,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request) ...@@ -100,7 +100,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request)
peerexists := false peerexists := false
received, err := s.settlement.TotalReceived(peer) received, err := s.swap.TotalReceived(peer)
if err != nil { if err != nil {
if !errors.Is(err, settlement.ErrPeerNoSettlements) { if !errors.Is(err, settlement.ErrPeerNoSettlements) {
s.logger.Debugf("debug api: settlements peer: get peer %s received settlement: %v", peer.String(), err) s.logger.Debugf("debug api: settlements peer: get peer %s received settlement: %v", peer.String(), err)
...@@ -116,7 +116,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request) ...@@ -116,7 +116,7 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request)
peerexists = true peerexists = true
} }
sent, err := s.settlement.TotalSent(peer) sent, err := s.swap.TotalSent(peer)
if err != nil { if err != nil {
if !errors.Is(err, settlement.ErrPeerNoSettlements) { if !errors.Is(err, settlement.ErrPeerNoSettlements) {
s.logger.Debugf("debug api: settlements peer: get peer %s sent settlement: %v", peer.String(), err) s.logger.Debugf("debug api: settlements peer: get peer %s sent settlement: %v", peer.String(), err)
...@@ -143,3 +143,59 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request) ...@@ -143,3 +143,59 @@ func (s *Service) peerSettlementsHandler(w http.ResponseWriter, r *http.Request)
SettlementSent: sent, SettlementSent: sent,
}) })
} }
func (s *Service) settlementsHandlerPseudosettle(w http.ResponseWriter, r *http.Request) {
settlementsSent, err := s.pseudosettle.SettlementsSent()
if err != nil {
jsonhttp.InternalServerError(w, errCantSettlements)
s.logger.Debugf("debug api: sent settlements: %v", err)
s.logger.Error("debug api: can not get sent settlements")
return
}
settlementsReceived, err := s.pseudosettle.SettlementsReceived()
if err != nil {
jsonhttp.InternalServerError(w, errCantSettlements)
s.logger.Debugf("debug api: received settlements: %v", err)
s.logger.Error("debug api: can not get received settlements")
return
}
totalReceived := big.NewInt(0)
totalSent := big.NewInt(0)
settlementResponses := make(map[string]settlementResponse)
for a, b := range settlementsSent {
settlementResponses[a] = settlementResponse{
Peer: a,
SettlementSent: b,
SettlementReceived: big.NewInt(0),
}
totalSent.Add(b, totalSent)
}
for a, b := range settlementsReceived {
if _, ok := settlementResponses[a]; ok {
t := settlementResponses[a]
t.SettlementReceived = b
settlementResponses[a] = t
} else {
settlementResponses[a] = settlementResponse{
Peer: a,
SettlementSent: big.NewInt(0),
SettlementReceived: b,
}
}
totalReceived.Add(b, totalReceived)
}
settlementResponsesArray := make([]settlementResponse, len(settlementResponses))
i := 0
for k := range settlementResponses {
settlementResponsesArray[i] = settlementResponses[k]
i++
}
jsonhttp.OK(w, settlementsResponse{TotalSettlementReceived: totalReceived, TotalSettlementSent: totalSent, Settlements: settlementResponsesArray})
}
...@@ -36,7 +36,7 @@ func TestSettlements(t *testing.T) { ...@@ -36,7 +36,7 @@ func TestSettlements(t *testing.T) {
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{mock.WithSettlementsSentFunc(settlementsSentFunc), mock.WithSettlementsRecvFunc(settlementsRecvFunc)}, SwapOpts: []mock.Option{mock.WithSettlementsSentFunc(settlementsSentFunc), mock.WithSettlementsRecvFunc(settlementsRecvFunc)},
}) })
expected := &debugapi.SettlementsResponse{ expected := &debugapi.SettlementsResponse{
...@@ -84,7 +84,7 @@ func TestSettlementsError(t *testing.T) { ...@@ -84,7 +84,7 @@ func TestSettlementsError(t *testing.T) {
return nil, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{mock.WithSettlementsSentFunc(settlementsSentFunc)}, SwapOpts: []mock.Option{mock.WithSettlementsSentFunc(settlementsSentFunc)},
}) })
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements", http.StatusInternalServerError, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements", http.StatusInternalServerError,
...@@ -101,7 +101,7 @@ func TestSettlementsPeers(t *testing.T) { ...@@ -101,7 +101,7 @@ func TestSettlementsPeers(t *testing.T) {
return big.NewInt(1000000000000000000), nil return big.NewInt(1000000000000000000), nil
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)}, SwapOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)},
}) })
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusOK, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusOK,
...@@ -124,7 +124,7 @@ func TestSettlementsPeersNoSettlements(t *testing.T) { ...@@ -124,7 +124,7 @@ func TestSettlementsPeersNoSettlements(t *testing.T) {
t.Run("no sent", func(t *testing.T) { t.Run("no sent", func(t *testing.T) {
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{ SwapOpts: []mock.Option{
mock.WithSettlementSentFunc(errFunc), mock.WithSettlementSentFunc(errFunc),
mock.WithSettlementRecvFunc(noErrFunc), mock.WithSettlementRecvFunc(noErrFunc),
}, },
...@@ -141,7 +141,7 @@ func TestSettlementsPeersNoSettlements(t *testing.T) { ...@@ -141,7 +141,7 @@ func TestSettlementsPeersNoSettlements(t *testing.T) {
t.Run("no received", func(t *testing.T) { t.Run("no received", func(t *testing.T) {
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{ SwapOpts: []mock.Option{
mock.WithSettlementSentFunc(noErrFunc), mock.WithSettlementSentFunc(noErrFunc),
mock.WithSettlementRecvFunc(errFunc), mock.WithSettlementRecvFunc(errFunc),
}, },
...@@ -164,7 +164,7 @@ func TestSettlementsPeersError(t *testing.T) { ...@@ -164,7 +164,7 @@ func TestSettlementsPeersError(t *testing.T) {
return nil, wantErr return nil, wantErr
} }
testServer := newTestServer(t, testServerOptions{ testServer := newTestServer(t, testServerOptions{
SettlementOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)}, SwapOpts: []mock.Option{mock.WithSettlementSentFunc(settlementSentFunc)},
}) })
jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusInternalServerError, jsonhttptest.Request(t, testServer.Client, http.MethodGet, "/settlements/"+peer, http.StatusInternalServerError,
......
...@@ -203,7 +203,7 @@ func InitSwap( ...@@ -203,7 +203,7 @@ func InitSwap(
chequebookService chequebook.Service, chequebookService chequebook.Service,
chequeStore chequebook.ChequeStore, chequeStore chequebook.ChequeStore,
cashoutService chequebook.CashoutService, cashoutService chequebook.CashoutService,
accountingAPI settlement.AccountingAPI, accounting settlement.Accounting,
) (*swap.Service, error) { ) (*swap.Service, error) {
swapProtocol := swapprotocol.New(p2ps, logger, overlayEthAddress) swapProtocol := swapprotocol.New(p2ps, logger, overlayEthAddress)
swapAddressBook := swap.NewAddressbook(stateStore) swapAddressBook := swap.NewAddressbook(stateStore)
...@@ -218,7 +218,7 @@ func InitSwap( ...@@ -218,7 +218,7 @@ func InitSwap(
networkID, networkID,
cashoutService, cashoutService,
p2ps, p2ps,
accountingAPI, accounting,
) )
swapProtocol.SetSwap(swapService) swapProtocol.SetSwap(swapService)
......
...@@ -54,7 +54,6 @@ import ( ...@@ -54,7 +54,6 @@ import (
"github.com/ethersphere/bee/pkg/recovery" "github.com/ethersphere/bee/pkg/recovery"
"github.com/ethersphere/bee/pkg/resolver/multiresolver" "github.com/ethersphere/bee/pkg/resolver/multiresolver"
"github.com/ethersphere/bee/pkg/retrieval" "github.com/ethersphere/bee/pkg/retrieval"
settlement "github.com/ethersphere/bee/pkg/settlement"
"github.com/ethersphere/bee/pkg/settlement/pseudosettle" "github.com/ethersphere/bee/pkg/settlement/pseudosettle"
"github.com/ethersphere/bee/pkg/settlement/swap" "github.com/ethersphere/bee/pkg/settlement/swap"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
...@@ -136,6 +135,11 @@ type Options struct { ...@@ -136,6 +135,11 @@ type Options struct {
BlockTime uint64 BlockTime uint64
} }
const (
refreshRate = int64(1000000000000)
basePrice = 1000000000
)
func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, signer crypto.Signer, networkID uint64, logger logging.Logger, libp2pPrivateKey, pssPrivateKey *ecdsa.PrivateKey, o Options) (b *Bee, err error) { func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, signer crypto.Signer, networkID uint64, logger logging.Logger, libp2pPrivateKey, pssPrivateKey *ecdsa.PrivateKey, o Options) (b *Bee, err error) {
tracer, tracerCloser, err := tracing.NewTracer(&tracing.Options{ tracer, tracerCloser, err := tracing.NewTracer(&tracing.Options{
Enabled: o.TracingEnabled, Enabled: o.TracingEnabled,
...@@ -419,7 +423,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -419,7 +423,6 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
} }
} }
var settlement settlement.Interface
var swapService *swap.Service var swapService *swap.Service
kad := kademlia.New(swarmAddress, addressbook, hive, p2ps, logger, kademlia.Options{Bootnodes: bootnodes, StandaloneMode: o.Standalone, BootnodeMode: o.BootnodeMode}) kad := kademlia.New(swarmAddress, addressbook, hive, p2ps, logger, kademlia.Options{Bootnodes: bootnodes, StandaloneMode: o.Standalone, BootnodeMode: o.BootnodeMode})
...@@ -445,7 +448,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -445,7 +448,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
return nil, fmt.Errorf("invalid payment threshold: %s", paymentThreshold) return nil, fmt.Errorf("invalid payment threshold: %s", paymentThreshold)
} }
pricer := pricer.NewFixedPricer(swarmAddress, 1000000000) pricer := pricer.NewFixedPricer(swarmAddress, basePrice)
minThreshold := pricer.MostExpensive() minThreshold := pricer.MostExpensive()
...@@ -472,6 +475,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -472,6 +475,7 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
if !ok { if !ok {
return nil, fmt.Errorf("invalid payment early: %s", paymentEarly) return nil, fmt.Errorf("invalid payment early: %s", paymentEarly)
} }
acc, err := accounting.NewAccounting( acc, err := accounting.NewAccounting(
paymentThreshold, paymentThreshold,
paymentTolerance, paymentTolerance,
...@@ -479,11 +483,19 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -479,11 +483,19 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
logger, logger,
stateStore, stateStore,
pricing, pricing,
big.NewInt(refreshRate),
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("accounting: %w", err) return nil, fmt.Errorf("accounting: %w", err)
} }
pseudosettleService := pseudosettle.New(p2ps, logger, stateStore, acc, big.NewInt(refreshRate), p2ps)
if err = p2ps.AddProtocol(pseudosettleService.Protocol()); err != nil {
return nil, fmt.Errorf("pseudosettle service: %w", err)
}
acc.SetRefreshFunc(pseudosettleService.Pay)
if o.SwapEnable { if o.SwapEnable {
swapService, err = InitSwap( swapService, err = InitSwap(
p2ps, p2ps,
...@@ -499,17 +511,9 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -499,17 +511,9 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
if err != nil { if err != nil {
return nil, err return nil, err
} }
settlement = swapService acc.SetPayFunc(swapService.Pay)
} else {
pseudosettleService := pseudosettle.New(p2ps, logger, stateStore, acc)
if err = p2ps.AddProtocol(pseudosettleService.Protocol()); err != nil {
return nil, fmt.Errorf("pseudosettle service: %w", err)
}
settlement = pseudosettleService
} }
acc.SetPayFunc(settlement.Pay)
pricing.SetPaymentThresholdObserver(acc) pricing.SetPaymentThresholdObserver(acc)
retrieve := retrieval.New(swarmAddress, storer, p2ps, kad, logger, acc, pricer, tracer) retrieve := retrieval.New(swarmAddress, storer, p2ps, kad, logger, acc, pricer, tracer)
...@@ -645,12 +649,14 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey, ...@@ -645,12 +649,14 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
debugAPIService.MustRegisterMetrics(l.Metrics()...) debugAPIService.MustRegisterMetrics(l.Metrics()...)
} }
if l, ok := settlement.(metrics.Collector); ok { debugAPIService.MustRegisterMetrics(pseudosettleService.Metrics()...)
debugAPIService.MustRegisterMetrics(l.Metrics()...)
if swapService != nil {
debugAPIService.MustRegisterMetrics(swapService.Metrics()...)
} }
// inject dependencies and configure full debug api http path routes // inject dependencies and configure full debug api http path routes
debugAPIService.Configure(p2ps, pingPong, kad, lightNodes, storer, tagService, acc, settlement, o.SwapEnable, swapService, chequebookService, batchStore) debugAPIService.Configure(p2ps, pingPong, kad, lightNodes, storer, tagService, acc, pseudosettleService, o.SwapEnable, swapService, chequebookService, batchStore)
} }
if err := kad.Start(p2pCtx); err != nil { if err := kad.Start(p2pCtx); err != nil {
......
...@@ -27,7 +27,7 @@ import ( ...@@ -27,7 +27,7 @@ import (
"github.com/ethersphere/bee/pkg/tags" "github.com/ethersphere/bee/pkg/tags"
"github.com/ethersphere/bee/pkg/topology" "github.com/ethersphere/bee/pkg/topology"
"github.com/ethersphere/bee/pkg/tracing" "github.com/ethersphere/bee/pkg/tracing"
"github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
opentracing "github.com/opentracing/opentracing-go" opentracing "github.com/opentracing/opentracing-go"
) )
...@@ -158,12 +158,15 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) ...@@ -158,12 +158,15 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
ps.logger.Errorf("pushsync: chunk store: %v", err) ps.logger.Errorf("pushsync: chunk store: %v", err)
} }
debit := ps.accounting.PrepareDebit(p.Address, price)
defer debit.Cleanup()
// return back receipt // return back receipt
receipt := pb.Receipt{Address: chunk.Address().Bytes()} receipt := pb.Receipt{Address: chunk.Address().Bytes()}
if err := w.WriteMsgWithContext(ctxd, &receipt); err != nil { if err := w.WriteMsgWithContext(ctxd, &receipt); err != nil {
return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err) return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err)
} }
return ps.accounting.Debit(p.Address, price) return debit.Apply()
} }
return ErrOutOfDepthReplication return ErrOutOfDepthReplication
...@@ -283,23 +286,29 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) ...@@ -283,23 +286,29 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
} }
// return back receipt // return back receipt
debit := ps.accounting.PrepareDebit(p.Address, price)
defer debit.Cleanup()
receipt := pb.Receipt{Address: chunk.Address().Bytes(), Signature: signature} receipt := pb.Receipt{Address: chunk.Address().Bytes(), Signature: signature}
if err := w.WriteMsgWithContext(ctx, &receipt); err != nil { if err := w.WriteMsgWithContext(ctx, &receipt); err != nil {
return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err) return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err)
} }
return ps.accounting.Debit(p.Address, price) return debit.Apply()
} }
return fmt.Errorf("handler: push to closest: %w", err) return fmt.Errorf("handler: push to closest: %w", err)
} }
debit := ps.accounting.PrepareDebit(p.Address, price)
defer debit.Cleanup()
// pass back the receipt // pass back the receipt
if err := w.WriteMsgWithContext(ctx, receipt); err != nil { if err := w.WriteMsgWithContext(ctx, receipt); err != nil {
return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err) return fmt.Errorf("send receipt to peer %s: %w", p.Address.String(), err)
} }
return ps.accounting.Debit(p.Address, price) return debit.Apply()
} }
// PushChunkToClosest sends chunk to the closest peer by opening a stream. It then waits for // PushChunkToClosest sends chunk to the closest peer by opening a stream. It then waits for
......
...@@ -362,6 +362,11 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e ...@@ -362,6 +362,11 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e
if err != nil { if err != nil {
return fmt.Errorf("stamp marshal: %w", err) return fmt.Errorf("stamp marshal: %w", err)
} }
chunkPrice := s.pricer.Price(chunk.Address())
debit := s.accounting.PrepareDebit(p.Address, chunkPrice)
defer debit.Cleanup()
if err := w.WriteMsgWithContext(ctx, &pb.Delivery{ if err := w.WriteMsgWithContext(ctx, &pb.Delivery{
Data: chunk.Data(), Data: chunk.Data(),
Stamp: stamp, Stamp: stamp,
...@@ -371,8 +376,6 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e ...@@ -371,8 +376,6 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e
s.logger.Tracef("retrieval protocol debiting peer %s", p.Address.String()) s.logger.Tracef("retrieval protocol debiting peer %s", p.Address.String())
chunkPrice := s.pricer.Price(chunk.Address())
// debit price from p's balance // debit price from p's balance
return s.accounting.Debit(p.Address, chunkPrice) return debit.Apply()
} }
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package settlement package settlement
import ( import (
"context"
"errors" "errors"
"math/big" "math/big"
...@@ -18,9 +17,6 @@ var ( ...@@ -18,9 +17,6 @@ var (
// Interface is the interface used by Accounting to trigger settlement // Interface is the interface used by Accounting to trigger settlement
type Interface interface { type Interface interface {
// Pay initiates a payment to the given peer
// It should return without error it is likely that the payment worked
Pay(ctx context.Context, peer swarm.Address, amount *big.Int)
// TotalSent returns the total amount sent to a peer // TotalSent returns the total amount sent to a peer
TotalSent(peer swarm.Address) (totalSent *big.Int, 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
...@@ -31,8 +27,9 @@ type Interface interface { ...@@ -31,8 +27,9 @@ type Interface interface {
SettlementsReceived() (map[string]*big.Int, error) SettlementsReceived() (map[string]*big.Int, error)
} }
type AccountingAPI interface { type Accounting interface {
PeerDebt(peer swarm.Address) (*big.Int, error) PeerDebt(peer swarm.Address) (*big.Int, error)
NotifyPaymentReceived(peer swarm.Address, amount *big.Int) error NotifyPaymentReceived(peer swarm.Address, amount *big.Int) error
NotifyPaymentSent(peer swarm.Address, amount *big.Int, receivedError error) NotifyPaymentSent(peer swarm.Address, amount *big.Int, receivedError error)
NotifyRefreshmentReceived(peer swarm.Address, amount *big.Int) error
} }
// Copyright 2021 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 pseudosettle
import (
"context"
"time"
"github.com/ethersphere/bee/pkg/p2p"
)
func (s *Service) SetTimeNow(f func() time.Time) {
s.timeNow = f
}
func (s *Service) SetTime(k int64) {
s.SetTimeNow(func() time.Time {
return time.Unix(k, 0)
})
}
func (s *Service) Init(ctx context.Context, peer p2p.Peer) error {
return s.init(ctx, peer)
}
func (s *Service) Terminate(peer p2p.Peer) error {
return s.terminate(peer)
}
...@@ -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 Payment struct { type Payment struct {
Amount uint64 `protobuf:"varint,1,opt,name=Amount,proto3" json:"Amount,omitempty"` Amount []byte `protobuf:"bytes,1,opt,name=Amount,proto3" json:"Amount,omitempty"`
} }
func (m *Payment) Reset() { *m = Payment{} } func (m *Payment) Reset() { *m = Payment{} }
...@@ -59,29 +59,84 @@ func (m *Payment) XXX_DiscardUnknown() { ...@@ -59,29 +59,84 @@ func (m *Payment) XXX_DiscardUnknown() {
var xxx_messageInfo_Payment proto.InternalMessageInfo var xxx_messageInfo_Payment proto.InternalMessageInfo
func (m *Payment) GetAmount() uint64 { func (m *Payment) GetAmount() []byte {
if m != nil { if m != nil {
return m.Amount return m.Amount
} }
return nil
}
type PaymentAck struct {
Amount []byte `protobuf:"bytes,1,opt,name=Amount,proto3" json:"Amount,omitempty"`
Timestamp int64 `protobuf:"varint,2,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"`
}
func (m *PaymentAck) Reset() { *m = PaymentAck{} }
func (m *PaymentAck) String() string { return proto.CompactTextString(m) }
func (*PaymentAck) ProtoMessage() {}
func (*PaymentAck) Descriptor() ([]byte, []int) {
return fileDescriptor_3ff21bb6c9cf5e84, []int{1}
}
func (m *PaymentAck) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *PaymentAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_PaymentAck.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *PaymentAck) XXX_Merge(src proto.Message) {
xxx_messageInfo_PaymentAck.Merge(m, src)
}
func (m *PaymentAck) XXX_Size() int {
return m.Size()
}
func (m *PaymentAck) XXX_DiscardUnknown() {
xxx_messageInfo_PaymentAck.DiscardUnknown(m)
}
var xxx_messageInfo_PaymentAck proto.InternalMessageInfo
func (m *PaymentAck) GetAmount() []byte {
if m != nil {
return m.Amount
}
return nil
}
func (m *PaymentAck) GetTimestamp() int64 {
if m != nil {
return m.Timestamp
}
return 0 return 0
} }
func init() { func init() {
proto.RegisterType((*Payment)(nil), "pseudosettle.Payment") proto.RegisterType((*Payment)(nil), "pseudosettle.Payment")
proto.RegisterType((*PaymentAck)(nil), "pseudosettle.PaymentAck")
} }
func init() { proto.RegisterFile("pseudosettle.proto", fileDescriptor_3ff21bb6c9cf5e84) } func init() { proto.RegisterFile("pseudosettle.proto", fileDescriptor_3ff21bb6c9cf5e84) }
var fileDescriptor_3ff21bb6c9cf5e84 = []byte{ var fileDescriptor_3ff21bb6c9cf5e84 = []byte{
// 114 bytes of a gzipped FileDescriptorProto // 148 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2a, 0x28, 0x4e, 0x2d, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2a, 0x28, 0x4e, 0x2d,
0x4d, 0xc9, 0x2f, 0x4e, 0x2d, 0x29, 0xc9, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4d, 0xc9, 0x2f, 0x4e, 0x2d, 0x29, 0xc9, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2,
0x41, 0x16, 0x53, 0x52, 0xe4, 0x62, 0x0f, 0x48, 0xac, 0xcc, 0x4d, 0xcd, 0x2b, 0x11, 0x12, 0xe3, 0x41, 0x16, 0x53, 0x52, 0xe4, 0x62, 0x0f, 0x48, 0xac, 0xcc, 0x4d, 0xcd, 0x2b, 0x11, 0x12, 0xe3,
0x62, 0x73, 0xcc, 0xcd, 0x2f, 0xcd, 0x2b, 0x91, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x09, 0x82, 0xf2, 0x62, 0x73, 0xcc, 0xcd, 0x2f, 0xcd, 0x2b, 0x91, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x09, 0x82, 0xf2,
0x9c, 0x64, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x94, 0x9c, 0xb8, 0xb8, 0xa0, 0x4a, 0x1c, 0x93, 0xb3, 0x71, 0xa9, 0x12, 0x92, 0xe1, 0xe2, 0x0c,
0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x8a, 0xa9, 0x20, 0x29, 0xc9, 0xcc, 0x4d, 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0x90, 0x60, 0x52, 0x60, 0xd4, 0x60, 0x0e, 0x42,
0x89, 0x0d, 0x6c, 0xaa, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x97, 0x5c, 0xf8, 0x6b, 0x00, 0x08, 0x38, 0xc9, 0x9c, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c,
0x00, 0x00, 0x13, 0x1e, 0xcb, 0x31, 0x5c, 0x78, 0x2c, 0xc7, 0x70, 0xe3, 0xb1, 0x1c, 0x43, 0x14, 0x53, 0x41,
0x52, 0x12, 0x1b, 0xd8, 0x65, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x87, 0xcb, 0xb8, 0x18,
0xaf, 0x00, 0x00, 0x00,
} }
func (m *Payment) Marshal() (dAtA []byte, err error) { func (m *Payment) Marshal() (dAtA []byte, err error) {
...@@ -104,10 +159,47 @@ func (m *Payment) MarshalToSizedBuffer(dAtA []byte) (int, error) { ...@@ -104,10 +159,47 @@ func (m *Payment) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if m.Amount != 0 { if len(m.Amount) > 0 {
i = encodeVarintPseudosettle(dAtA, i, uint64(m.Amount)) i -= len(m.Amount)
copy(dAtA[i:], m.Amount)
i = encodeVarintPseudosettle(dAtA, i, uint64(len(m.Amount)))
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *PaymentAck) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *PaymentAck) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *PaymentAck) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Timestamp != 0 {
i = encodeVarintPseudosettle(dAtA, i, uint64(m.Timestamp))
i-- i--
dAtA[i] = 0x8 dAtA[i] = 0x10
}
if len(m.Amount) > 0 {
i -= len(m.Amount)
copy(dAtA[i:], m.Amount)
i = encodeVarintPseudosettle(dAtA, i, uint64(len(m.Amount)))
i--
dAtA[i] = 0xa
} }
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
...@@ -129,8 +221,25 @@ func (m *Payment) Size() (n int) { ...@@ -129,8 +221,25 @@ func (m *Payment) Size() (n int) {
} }
var l int var l int
_ = l _ = l
if m.Amount != 0 { l = len(m.Amount)
n += 1 + sovPseudosettle(uint64(m.Amount)) if l > 0 {
n += 1 + l + sovPseudosettle(uint64(l))
}
return n
}
func (m *PaymentAck) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = len(m.Amount)
if l > 0 {
n += 1 + l + sovPseudosettle(uint64(l))
}
if m.Timestamp != 0 {
n += 1 + sovPseudosettle(uint64(m.Timestamp))
} }
return n return n
} }
...@@ -171,10 +280,131 @@ func (m *Payment) Unmarshal(dAtA []byte) error { ...@@ -171,10 +280,131 @@ func (m *Payment) 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 Amount", wireType) return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
} }
m.Amount = 0 var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPseudosettle
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthPseudosettle
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthPseudosettle
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Amount = append(m.Amount[:0], dAtA[iNdEx:postIndex]...)
if m.Amount == nil {
m.Amount = []byte{}
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipPseudosettle(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthPseudosettle
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPseudosettle
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *PaymentAck) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPseudosettle
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: PaymentAck: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: PaymentAck: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowPseudosettle
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthPseudosettle
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthPseudosettle
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Amount = append(m.Amount[:0], dAtA[iNdEx:postIndex]...)
if m.Amount == nil {
m.Amount = []byte{}
}
iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
}
m.Timestamp = 0
for shift := uint(0); ; shift += 7 { for shift := uint(0); ; shift += 7 {
if shift >= 64 { if shift >= 64 {
return ErrIntOverflowPseudosettle return ErrIntOverflowPseudosettle
...@@ -184,7 +414,7 @@ func (m *Payment) Unmarshal(dAtA []byte) error { ...@@ -184,7 +414,7 @@ func (m *Payment) Unmarshal(dAtA []byte) error {
} }
b := dAtA[iNdEx] b := dAtA[iNdEx]
iNdEx++ iNdEx++
m.Amount |= uint64(b&0x7F) << shift m.Timestamp |= int64(b&0x7F) << shift
if b < 0x80 { if b < 0x80 {
break break
} }
......
...@@ -9,5 +9,10 @@ package pseudosettle; ...@@ -9,5 +9,10 @@ package pseudosettle;
option go_package = "pb"; option go_package = "pb";
message Payment { message Payment {
uint64 Amount = 1; bytes Amount = 1;
} }
message PaymentAck {
bytes Amount = 1;
int64 Timestamp = 2;
}
\ No newline at end of file
This diff is collapsed.
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/settlement"
"github.com/ethersphere/bee/pkg/settlement/swap" "github.com/ethersphere/bee/pkg/settlement/swap"
"github.com/ethersphere/bee/pkg/settlement/swap/chequebook" "github.com/ethersphere/bee/pkg/settlement/swap/chequebook"
"github.com/ethersphere/bee/pkg/swarm" "github.com/ethersphere/bee/pkg/swarm"
...@@ -120,7 +119,7 @@ func WithCashoutStatusFunc(f func(ctx context.Context, peer swarm.Address) (*che ...@@ -120,7 +119,7 @@ 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) swap.Interface {
mock := new(Service) mock := new(Service)
mock.settlementsSent = make(map[string]*big.Int) mock.settlementsSent = make(map[string]*big.Int)
mock.settlementsRecv = make(map[string]*big.Int) mock.settlementsRecv = make(map[string]*big.Int)
...@@ -130,14 +129,6 @@ func New(opts ...Option) settlement.Interface { ...@@ -130,14 +129,6 @@ func New(opts ...Option) settlement.Interface {
return mock return mock
} }
func NewApiInterface(opts ...Option) swap.ApiInterface {
mock := new(Service)
for _, o := range opts {
o.apply(mock)
}
return mock
}
// ReceiveCheque is the mock ReceiveCheque function of swap. // ReceiveCheque is the mock ReceiveCheque function of swap.
func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque *chequebook.SignedCheque) (err error) { func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque *chequebook.SignedCheque) (err error) {
if s.receiveChequeFunc != nil { if s.receiveChequeFunc != nil {
......
...@@ -30,7 +30,8 @@ var ( ...@@ -30,7 +30,8 @@ var (
ErrUnknownBeneficary = errors.New("unknown beneficiary for peer") ErrUnknownBeneficary = errors.New("unknown beneficiary for peer")
) )
type ApiInterface interface { type Interface interface {
settlement.Interface
// LastSentCheque returns the last sent cheque for the peer // LastSentCheque returns the last sent cheque for the peer
LastSentCheque(peer swarm.Address) (*chequebook.SignedCheque, error) LastSentCheque(peer swarm.Address) (*chequebook.SignedCheque, error)
// LastSentCheques returns the list of last sent cheques for all peers // LastSentCheques returns the list of last sent cheques for all peers
...@@ -47,33 +48,33 @@ type ApiInterface interface { ...@@ -47,33 +48,33 @@ type ApiInterface interface {
// Service is the implementation of the swap settlement layer. // Service is the implementation of the swap settlement layer.
type Service struct { type Service struct {
proto swapprotocol.Interface proto swapprotocol.Interface
logger logging.Logger logger logging.Logger
store storage.StateStorer store storage.StateStorer
accountingAPI settlement.AccountingAPI accounting settlement.Accounting
metrics metrics metrics metrics
chequebook chequebook.Service chequebook chequebook.Service
chequeStore chequebook.ChequeStore chequeStore chequebook.ChequeStore
cashout chequebook.CashoutService cashout chequebook.CashoutService
p2pService p2p.Service p2pService p2p.Service
addressbook Addressbook addressbook Addressbook
networkID uint64 networkID uint64
} }
// New creates a new swap Service. // New creates a new swap Service.
func New(proto swapprotocol.Interface, logger logging.Logger, store storage.StateStorer, chequebook chequebook.Service, chequeStore chequebook.ChequeStore, addressbook Addressbook, networkID uint64, cashout chequebook.CashoutService, p2pService p2p.Service, accountingAPI settlement.AccountingAPI) *Service { func New(proto swapprotocol.Interface, logger logging.Logger, store storage.StateStorer, chequebook chequebook.Service, chequeStore chequebook.ChequeStore, addressbook Addressbook, networkID uint64, cashout chequebook.CashoutService, p2pService p2p.Service, accounting settlement.Accounting) *Service {
return &Service{ return &Service{
proto: proto, proto: proto,
logger: logger, logger: logger,
store: store, store: store,
metrics: newMetrics(), metrics: newMetrics(),
chequebook: chequebook, chequebook: chequebook,
chequeStore: chequeStore, chequeStore: chequeStore,
addressbook: addressbook, addressbook: addressbook,
networkID: networkID, networkID: networkID,
cashout: cashout, cashout: cashout,
p2pService: p2pService, p2pService: p2pService,
accountingAPI: accountingAPI, accounting: accounting,
} }
} }
...@@ -101,10 +102,11 @@ func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque ...@@ -101,10 +102,11 @@ func (s *Service) ReceiveCheque(ctx context.Context, peer swarm.Address, cheque
} }
} }
s.metrics.TotalReceived.Add(float64(amount.Uint64())) tot, _ := big.NewFloat(0).SetInt(amount).Float64()
s.metrics.TotalReceived.Add(tot)
s.metrics.ChequesReceived.Inc() s.metrics.ChequesReceived.Inc()
return s.accountingAPI.NotifyPaymentReceived(peer, amount) return s.accounting.NotifyPaymentReceived(peer, amount)
} }
// Pay initiates a payment to the given peer // Pay initiates a payment to the given peer
...@@ -112,7 +114,7 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int) ...@@ -112,7 +114,7 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int)
var err error var err error
defer func() { defer func() {
if err != nil { if err != nil {
s.accountingAPI.NotifyPaymentSent(peer, nil, err) s.accounting.NotifyPaymentSent(peer, amount, err)
} }
}() }()
beneficiary, known, err := s.addressbook.Beneficiary(peer) beneficiary, known, err := s.addressbook.Beneficiary(peer)
...@@ -136,14 +138,14 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int) ...@@ -136,14 +138,14 @@ func (s *Service) Pay(ctx context.Context, peer swarm.Address, amount *big.Int)
} }
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.accountingAPI.NotifyPaymentSent(peer, amount, nil) s.accounting.NotifyPaymentSent(peer, amount, nil)
amountFloat, _ := big.NewFloat(0).SetInt(amount).Float64() amountFloat, _ := big.NewFloat(0).SetInt(amount).Float64()
s.metrics.TotalSent.Add(amountFloat) s.metrics.TotalSent.Add(amountFloat)
s.metrics.ChequesSent.Inc() s.metrics.ChequesSent.Inc()
} }
func (s *Service) SetAccountingAPI(accountingAPI settlement.AccountingAPI) { func (s *Service) SetAccounting(accounting settlement.Accounting) {
s.accountingAPI = accountingAPI s.accounting = accounting
} }
// TotalSent returns the total amount sent to a peer // TotalSent returns the total amount sent to a peer
......
...@@ -70,6 +70,10 @@ func (t *testObserver) NotifyPaymentReceived(peer swarm.Address, amount *big.Int ...@@ -70,6 +70,10 @@ func (t *testObserver) NotifyPaymentReceived(peer swarm.Address, amount *big.Int
return nil return nil
} }
func (t *testObserver) NotifyRefreshmentReceived(peer swarm.Address, amount *big.Int) error {
return nil
}
func (t *testObserver) NotifyPaymentSent(peer swarm.Address, amount *big.Int, err error) { func (t *testObserver) NotifyPaymentSent(peer swarm.Address, amount *big.Int, err error) {
t.sentCalled <- notifyPaymentSentCall{ t.sentCalled <- notifyPaymentSentCall{
peer: peer, peer: peer,
...@@ -423,7 +427,7 @@ func TestPayIssueError(t *testing.T) { ...@@ -423,7 +427,7 @@ func TestPayIssueError(t *testing.T) {
) )
observer := newTestObserver() observer := newTestObserver()
swap.SetAccountingAPI(observer) swap.SetAccounting(observer)
swap.Pay(context.Background(), peer, amount) swap.Pay(context.Background(), peer, amount)
select { select {
......
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