Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
3217c6e1
Unverified
Commit
3217c6e1
authored
Apr 14, 2021
by
metacertain
Committed by
GitHub
Apr 14, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Pricing no protocol updates (#1563)
pushsync, retrieval, pricing: Pricing no protocol updates
parent
78aba90f
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
96 additions
and
1475 deletions
+96
-1475
node.go
pkg/node/node.go
+2
-4
export_test.go
pkg/pricer/export_test.go
+0
-13
pricer.go
pkg/pricer/mock/pricer.go
+9
-100
pricer.go
pkg/pricer/pricer.go
+18
-315
pricer_test.go
pkg/pricer/pricer_test.go
+0
-373
pricing.pb.go
pkg/pricing/pb/pricing.pb.go
+7
-118
pricing.proto
pkg/pricing/pb/pricing.proto
+0
-1
pricing.go
pkg/pricing/pricing.go
+2
-48
pricing_test.go
pkg/pricing/pricing_test.go
+2
-109
pushsync.go
pkg/pushsync/pushsync.go
+12
-49
pushsync_test.go
pkg/pushsync/pushsync_test.go
+10
-164
repair_test.go
pkg/recovery/repair_test.go
+1
-1
retrieval.go
pkg/retrieval/retrieval.go
+4
-34
retrieval_test.go
pkg/retrieval/retrieval_test.go
+19
-146
mock.go
pkg/topology/mock/mock.go
+10
-0
No files found.
pkg/node/node.go
View file @
3217c6e1
...
...
@@ -324,11 +324,9 @@ func NewBee(addr string, swarmAddress swarm.Address, publicKey ecdsa.PublicKey,
return
nil
,
fmt
.
Errorf
(
"invalid payment threshold: %s"
,
paymentThreshold
)
}
pricer
:=
pricer
.
New
(
logger
,
stateStore
,
swarmAddress
,
1000000000
)
pricer
.
SetTopology
(
kad
)
pricer
:=
pricer
.
NewFixedPricer
(
swarmAddress
,
1000000000
)
pricing
:=
pricing
.
New
(
p2ps
,
logger
,
paymentThreshold
,
pricer
)
pricing
.
SetPriceTableObserver
(
pricer
)
pricing
:=
pricing
.
New
(
p2ps
,
logger
,
paymentThreshold
)
if
err
=
p2ps
.
AddProtocol
(
pricing
.
Protocol
());
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"pricing service: %w"
,
err
)
...
...
pkg/pricer/export_test.go
deleted
100644 → 0
View file @
78aba90f
// 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
pricer
import
(
"github.com/ethersphere/bee/pkg/swarm"
)
func
(
s
*
Pricer
)
PeerPricePO
(
peer
swarm
.
Address
,
po
uint8
)
(
uint64
,
error
)
{
return
s
.
peerPricePO
(
peer
,
po
)
}
pkg/pricer/mock/pricer.go
View file @
3217c6e1
...
...
@@ -5,116 +5,25 @@
package
mock
import
(
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/swarm"
)
type
Service
struct
{
peerPrice
uint64
price
uint64
peerPriceFunc
func
(
peer
,
chunk
swarm
.
Address
)
uint64
priceForPeerFunc
func
(
peer
,
chunk
swarm
.
Address
)
uint64
priceTableFunc
func
()
(
priceTable
[]
uint64
)
notifyPriceTableFunc
func
(
peer
swarm
.
Address
,
priceTable
[]
uint64
)
error
priceHeadlerFunc
func
(
p2p
.
Headers
,
swarm
.
Address
)
p2p
.
Headers
notifyPeerPriceFunc
func
(
peer
swarm
.
Address
,
price
uint64
,
index
uint8
)
error
type
MockPricer
struct
{
peerPrice
uint64
price
uint64
}
// WithReserveFunc sets the mock Reserve function
func
WithPeerPriceFunc
(
f
func
(
peer
,
chunk
swarm
.
Address
)
uint64
)
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
peerPriceFunc
=
f
})
}
// WithReleaseFunc sets the mock Release function
func
WithPriceForPeerFunc
(
f
func
(
peer
,
chunk
swarm
.
Address
)
uint64
)
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
priceForPeerFunc
=
f
})
}
func
WithPrice
(
p
uint64
)
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
price
=
p
})
}
func
WithPeerPrice
(
p
uint64
)
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
peerPrice
=
p
})
}
// WithPriceTableFunc sets the mock Release function
func
WithPriceTableFunc
(
f
func
()
(
priceTable
[]
uint64
))
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
priceTableFunc
=
f
})
}
func
WithPriceHeadlerFunc
(
f
func
(
headers
p2p
.
Headers
,
addr
swarm
.
Address
)
p2p
.
Headers
)
Option
{
return
optionFunc
(
func
(
s
*
Service
)
{
s
.
priceHeadlerFunc
=
f
})
}
func
NewMockService
(
opts
...
Option
)
*
Service
{
mock
:=
new
(
Service
)
mock
.
price
=
10
mock
.
peerPrice
=
10
for
_
,
o
:=
range
opts
{
o
.
apply
(
mock
)
func
NewMockService
(
price
,
peerPrice
uint64
)
*
MockPricer
{
return
&
MockPricer
{
peerPrice
:
peerPrice
,
price
:
price
,
}
return
mock
}
func
(
pricer
*
Service
)
PeerPrice
(
peer
,
chunk
swarm
.
Address
)
uint64
{
if
pricer
.
peerPriceFunc
!=
nil
{
return
pricer
.
peerPriceFunc
(
peer
,
chunk
)
}
func
(
pricer
*
MockPricer
)
PeerPrice
(
peer
,
chunk
swarm
.
Address
)
uint64
{
return
pricer
.
peerPrice
}
func
(
pricer
*
Service
)
PriceForPeer
(
peer
,
chunk
swarm
.
Address
)
uint64
{
if
pricer
.
priceForPeerFunc
!=
nil
{
return
pricer
.
priceForPeerFunc
(
peer
,
chunk
)
}
func
(
pricer
*
MockPricer
)
Price
(
chunk
swarm
.
Address
)
uint64
{
return
pricer
.
price
}
func
(
pricer
*
Service
)
PriceTable
()
(
priceTable
[]
uint64
)
{
if
pricer
.
priceTableFunc
!=
nil
{
return
pricer
.
priceTableFunc
()
}
return
nil
}
func
(
pricer
*
Service
)
NotifyPriceTable
(
peer
swarm
.
Address
,
priceTable
[]
uint64
)
error
{
if
pricer
.
notifyPriceTableFunc
!=
nil
{
return
pricer
.
notifyPriceTableFunc
(
peer
,
priceTable
)
}
return
nil
}
func
(
pricer
*
Service
)
PriceHeadler
(
headers
p2p
.
Headers
,
addr
swarm
.
Address
)
p2p
.
Headers
{
if
pricer
.
priceHeadlerFunc
!=
nil
{
return
pricer
.
priceHeadlerFunc
(
headers
,
addr
)
}
return
p2p
.
Headers
{}
}
func
(
pricer
*
Service
)
NotifyPeerPrice
(
peer
swarm
.
Address
,
price
uint64
,
index
uint8
)
error
{
if
pricer
.
notifyPeerPriceFunc
!=
nil
{
return
pricer
.
notifyPeerPriceFunc
(
peer
,
price
,
index
)
}
return
nil
}
// Option is the option passed to the mock accounting service
type
Option
interface
{
apply
(
*
Service
)
}
type
optionFunc
func
(
*
Service
)
func
(
f
optionFunc
)
apply
(
r
*
Service
)
{
f
(
r
)
}
pkg/pricer/pricer.go
View file @
3217c6e1
...
...
@@ -5,334 +5,37 @@
package
pricer
import
(
"errors"
"fmt"
"sync"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/pricer/headerutils"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/topology"
)
const
(
priceTablePrefix
string
=
"pricetable_"
)
var
_
Interface
=
(
*
Pricer
)(
nil
)
// Pricer returns pricing information for chunk hashes and proximity orders
// Pricer returns pricing information for chunk hashes.
type
Interface
interface
{
// PriceTable returns pricetable stored for the node
PriceTable
()
[]
uint64
// PeerPrice is the price the peer charges for a given chunk hash.
PeerPrice
(
peer
,
chunk
swarm
.
Address
)
uint64
// PriceForPeer is the price we charge a peer for a given chunk hash.
PriceForPeer
(
peer
,
chunk
swarm
.
Address
)
uint64
// NotifyPriceTable saves a provided pricetable for a peer to store
NotifyPriceTable
(
peer
swarm
.
Address
,
priceTable
[]
uint64
)
error
// NotifyPeerPrice changes a value that belongs to an index in a peer pricetable
NotifyPeerPrice
(
peer
swarm
.
Address
,
price
uint64
,
index
uint8
)
error
// PriceHeadler creates response headers with pricing information
PriceHeadler
(
p2p
.
Headers
,
swarm
.
Address
)
p2p
.
Headers
}
var
(
ErrPersistingBalancePeer
=
errors
.
New
(
"failed to persist pricetable for peer"
)
)
type
pricingPeer
struct
{
lock
sync
.
Mutex
}
type
Pricer
struct
{
pricingPeersMu
sync
.
Mutex
pricingPeers
map
[
string
]
*
pricingPeer
logger
logging
.
Logger
store
storage
.
StateStorer
overlay
swarm
.
Address
topology
topology
.
Driver
poPrice
uint64
}
func
New
(
logger
logging
.
Logger
,
store
storage
.
StateStorer
,
overlay
swarm
.
Address
,
poPrice
uint64
)
*
Pricer
{
return
&
Pricer
{
logger
:
logger
,
pricingPeers
:
make
(
map
[
string
]
*
pricingPeer
),
store
:
store
,
overlay
:
overlay
,
poPrice
:
poPrice
,
}
}
// PriceTable returns the pricetable stored for the node
// If not available, the default pricetable is provided
func
(
s
*
Pricer
)
PriceTable
()
(
priceTable
[]
uint64
)
{
err
:=
s
.
store
.
Get
(
priceTableKey
(),
&
priceTable
)
if
err
!=
nil
{
priceTable
=
s
.
defaultPriceTable
()
}
return
priceTable
}
// peerPriceTable returns the price table stored for the given peer.
// If we can't get price table from store, we return the default price table
func
(
s
*
Pricer
)
peerPriceTable
(
peer
swarm
.
Address
)
(
priceTable
[]
uint64
)
{
err
:=
s
.
store
.
Get
(
peerPriceTableKey
(
peer
),
&
priceTable
)
if
err
!=
nil
{
priceTable
=
s
.
defaultPriceTable
()
// get default pricetable
}
return
priceTable
}
// PriceForPeer returns the price for the PO of a chunk from the table stored for the node.
// Taking into consideration that the peer might be an in-neighborhood peer,
// if the chunk is at least neighborhood depth proximate to both the node and the peer, the price is 0
func
(
s
*
Pricer
)
PriceForPeer
(
peer
,
chunk
swarm
.
Address
)
uint64
{
proximity
:=
swarm
.
Proximity
(
s
.
overlay
.
Bytes
(),
chunk
.
Bytes
())
neighborhoodDepth
:=
s
.
neighborhoodDepth
()
if
proximity
>=
neighborhoodDepth
{
peerproximity
:=
swarm
.
Proximity
(
peer
.
Bytes
(),
chunk
.
Bytes
())
if
peerproximity
>=
neighborhoodDepth
{
return
0
}
}
price
,
err
:=
s
.
pricePO
(
proximity
)
if
err
!=
nil
{
price
=
s
.
defaultPrice
(
proximity
)
}
return
price
}
// priceWithIndexForPeer returns price for a chunk for a given peer,
// and the index of PO in pricetable which is used
func
(
s
*
Pricer
)
priceWithIndexForPeer
(
peer
,
chunk
swarm
.
Address
)
(
price
uint64
,
index
uint8
)
{
proximity
:=
swarm
.
Proximity
(
s
.
overlay
.
Bytes
(),
chunk
.
Bytes
())
neighborhoodDepth
:=
s
.
neighborhoodDepth
()
priceTable
:=
s
.
PriceTable
()
if
int
(
proximity
)
>=
len
(
priceTable
)
{
proximity
=
uint8
(
len
(
priceTable
)
-
1
)
}
if
proximity
>=
neighborhoodDepth
{
proximity
=
neighborhoodDepth
peerproximity
:=
swarm
.
Proximity
(
peer
.
Bytes
(),
chunk
.
Bytes
())
if
peerproximity
>=
neighborhoodDepth
{
return
0
,
proximity
}
}
return
priceTable
[
proximity
],
proximity
}
// pricePO returns the price for a PO from the table stored for the node.
func
(
s
*
Pricer
)
pricePO
(
po
uint8
)
(
uint64
,
error
)
{
priceTable
:=
s
.
PriceTable
()
proximity
:=
po
if
int
(
po
)
>=
len
(
priceTable
)
{
proximity
=
uint8
(
len
(
priceTable
)
-
1
)
}
return
priceTable
[
proximity
],
nil
}
// PeerPrice returns the price for the PO of a chunk from the table stored for the given peer.
// Taking into consideration that the peer might be an in-neighborhood peer,
// if the chunk is at least neighborhood depth proximate to both the node and the peer, the price is 0
func
(
s
*
Pricer
)
PeerPrice
(
peer
,
chunk
swarm
.
Address
)
uint64
{
proximity
:=
swarm
.
Proximity
(
peer
.
Bytes
(),
chunk
.
Bytes
())
// Determine neighborhood depth presumed by peer based on pricetable rows
var
priceTable
[]
uint64
err
:=
s
.
store
.
Get
(
peerPriceTableKey
(
peer
),
&
priceTable
)
peerNeighborhoodDepth
:=
uint8
(
len
(
priceTable
)
-
1
)
if
err
!=
nil
{
peerNeighborhoodDepth
=
s
.
neighborhoodDepth
()
}
// determine whether the chunk is within presumed neighborhood depth of peer
if
proximity
>=
peerNeighborhoodDepth
{
// determine if the chunk is within presumed neighborhood depth of peer to us
selfproximity
:=
swarm
.
Proximity
(
s
.
overlay
.
Bytes
(),
chunk
.
Bytes
())
if
selfproximity
>=
peerNeighborhoodDepth
{
return
0
}
}
price
,
err
:=
s
.
peerPricePO
(
peer
,
proximity
)
if
err
!=
nil
{
price
=
s
.
defaultPrice
(
proximity
)
}
return
price
}
// peerPricePO returns the price for a PO from the table stored for the given peer.
func
(
s
*
Pricer
)
peerPricePO
(
peer
swarm
.
Address
,
po
uint8
)
(
uint64
,
error
)
{
var
priceTable
[]
uint64
err
:=
s
.
store
.
Get
(
peerPriceTableKey
(
peer
),
&
priceTable
)
if
err
!=
nil
{
if
!
errors
.
Is
(
err
,
storage
.
ErrNotFound
)
{
return
0
,
err
}
priceTable
=
s
.
defaultPriceTable
()
}
proximity
:=
po
if
int
(
po
)
>=
len
(
priceTable
)
{
proximity
=
uint8
(
len
(
priceTable
)
-
1
)
}
return
priceTable
[
proximity
],
nil
}
// peerPriceTableKey returns the price table storage key for the given peer.
func
peerPriceTableKey
(
peer
swarm
.
Address
)
string
{
return
fmt
.
Sprintf
(
"%s%s"
,
priceTablePrefix
,
peer
.
String
())
}
// priceTableKey returns the price table storage key for own price table
func
priceTableKey
()
string
{
return
fmt
.
Sprintf
(
"%s%s"
,
priceTablePrefix
,
"self"
)
}
func
(
s
*
Pricer
)
getPricingPeer
(
peer
swarm
.
Address
)
(
*
pricingPeer
,
error
)
{
s
.
pricingPeersMu
.
Lock
()
defer
s
.
pricingPeersMu
.
Unlock
()
peerData
,
ok
:=
s
.
pricingPeers
[
peer
.
String
()]
if
!
ok
{
peerData
=
&
pricingPeer
{}
s
.
pricingPeers
[
peer
.
String
()]
=
peerData
}
return
peerData
,
nil
// Price is the price we charge for a given chunk hash.
Price
(
chunk
swarm
.
Address
)
uint64
}
func
(
s
*
Pricer
)
storePriceTable
(
peer
swarm
.
Address
,
priceTable
[]
uint64
)
error
{
s
.
logger
.
Tracef
(
"Storing pricetable %v for peer %v"
,
priceTable
,
peer
)
err
:=
s
.
store
.
Put
(
peerPriceTableKey
(
peer
),
priceTable
)
if
err
!=
nil
{
return
err
}
return
nil
// FixedPricer is a Pricer that has a fixed price for chunks.
type
FixedPricer
struct
{
overlay
swarm
.
Address
poPrice
uint64
}
// N
otifyPriceTable should be called to notify pricer of changes in the peers pricetable
func
(
s
*
Pricer
)
NotifyPriceTable
(
peer
swarm
.
Address
,
priceTable
[]
uint64
)
erro
r
{
pricingPeer
,
err
:=
s
.
getPricingPeer
(
peer
)
if
err
!=
nil
{
return
err
// N
ewFixedPricer returns a new FixedPricer with a given price.
func
NewFixedPricer
(
overlay
swarm
.
Address
,
poPrice
uint64
)
*
FixedPrice
r
{
return
&
FixedPricer
{
overlay
:
overlay
,
poPrice
:
poPrice
,
}
pricingPeer
.
lock
.
Lock
()
defer
pricingPeer
.
lock
.
Unlock
()
return
s
.
storePriceTable
(
peer
,
priceTable
)
}
func
(
s
*
Pricer
)
NotifyPeerPrice
(
peer
swarm
.
Address
,
price
uint64
,
index
uint8
)
error
{
if
price
==
0
{
return
nil
}
pricingPeer
,
err
:=
s
.
getPricingPeer
(
peer
)
if
err
!=
nil
{
return
err
}
pricingPeer
.
lock
.
Lock
()
defer
pricingPeer
.
lock
.
Unlock
()
priceTable
:=
s
.
peerPriceTable
(
peer
)
currentIndexDepth
:=
uint8
(
len
(
priceTable
))
-
1
if
index
<=
currentIndexDepth
{
// Simple case, already have index depth, single value change
priceTable
[
index
]
=
price
return
s
.
storePriceTable
(
peer
,
priceTable
)
}
// Complicated case, index is larger than depth of already known table
newPriceTable
:=
make
([]
uint64
,
index
+
1
)
// Copy previous content
_
=
copy
(
newPriceTable
,
priceTable
)
// Check how many rows are missing
numberOfMissingRows
:=
index
-
currentIndexDepth
for
i
:=
uint8
(
0
);
i
<
numberOfMissingRows
;
i
++
{
currentrow
:=
index
-
i
newPriceTable
[
currentrow
]
=
price
+
uint64
(
i
)
*
s
.
poPrice
s
.
logger
.
Debugf
(
"Guessing price %v for extending pricetable %v for peer %v"
,
newPriceTable
[
currentrow
],
newPriceTable
,
peer
)
}
return
s
.
storePriceTable
(
peer
,
newPriceTable
)
}
func
(
s
*
Pricer
)
defaultPriceTable
()
[]
uint64
{
neighborhoodDepth
:=
s
.
neighborhoodDepth
()
priceTable
:=
make
([]
uint64
,
neighborhoodDepth
+
1
)
for
i
:=
uint8
(
0
);
i
<=
neighborhoodDepth
;
i
++
{
priceTable
[
i
]
=
uint64
(
neighborhoodDepth
-
i
+
1
)
*
s
.
poPrice
}
return
priceTable
}
func
(
s
*
Pricer
)
defaultPrice
(
po
uint8
)
uint64
{
neighborhoodDepth
:=
s
.
neighborhoodDepth
()
if
po
>
neighborhoodDepth
{
po
=
neighborhoodDepth
}
return
uint64
(
neighborhoodDepth
-
po
+
1
)
*
s
.
poPrice
}
func
(
s
*
Pricer
)
neighborhoodDepth
()
uint8
{
var
neighborhoodDepth
uint8
if
s
.
topology
!=
nil
{
neighborhoodDepth
=
s
.
topology
.
NeighborhoodDepth
()
}
return
neighborhoodDepth
}
func
(
s
*
Pricer
)
PriceHeadler
(
receivedHeaders
p2p
.
Headers
,
peerAddress
swarm
.
Address
)
(
returnHeaders
p2p
.
Headers
)
{
chunkAddress
,
receivedPrice
,
err
:=
headerutils
.
ParsePricingHeaders
(
receivedHeaders
)
if
err
!=
nil
{
return
p2p
.
Headers
{
"error"
:
[]
byte
(
"Error reading pricing headers"
),
}
}
s
.
logger
.
Debugf
(
"price headler: received target %v with price as %v, from peer %s"
,
chunkAddress
,
receivedPrice
,
peerAddress
)
checkPrice
,
index
:=
s
.
priceWithIndexForPeer
(
peerAddress
,
chunkAddress
)
returnHeaders
,
err
=
headerutils
.
MakePricingResponseHeaders
(
checkPrice
,
chunkAddress
,
index
)
if
err
!=
nil
{
return
p2p
.
Headers
{
"error"
:
[]
byte
(
"Error creating response pricing headers"
),
}
}
s
.
logger
.
Debugf
(
"price headler: response target %v with price as %v, for peer %s"
,
chunkAddress
,
checkPrice
,
peerAddress
)
return
returnHeaders
// PeerPrice implements Pricer.
func
(
pricer
*
FixedPricer
)
PeerPrice
(
peer
,
chunk
swarm
.
Address
)
uint64
{
return
uint64
(
swarm
.
MaxPO
-
swarm
.
Proximity
(
peer
.
Bytes
(),
chunk
.
Bytes
())
+
1
)
*
pricer
.
poPrice
}
func
(
s
*
Pricer
)
SetTopology
(
top
topology
.
Driver
)
{
s
.
topology
=
top
// Price implements Pricer.
func
(
pricer
*
FixedPricer
)
Price
(
chunk
swarm
.
Address
)
uint64
{
return
pricer
.
PeerPrice
(
pricer
.
overlay
,
chunk
)
}
pkg/pricer/pricer_test.go
deleted
100644 → 0
View file @
78aba90f
// 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
pricer_test
import
(
"encoding/binary"
"io/ioutil"
"reflect"
"testing"
mockkad
"github.com/ethersphere/bee/pkg/kademlia/mock"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/pricer"
"github.com/ethersphere/bee/pkg/pricer/headerutils"
"github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/swarm"
)
func
TestPriceTableDefaultTables
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
overlay
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
defer
store
.
Close
()
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepthCalls
(
0
,
0
,
2
,
3
,
5
,
9
))
pricer
.
SetTopology
(
kad
)
table0
:=
[]
uint64
{
10
}
table1
:=
[]
uint64
{
30
,
20
,
10
}
table2
:=
[]
uint64
{
40
,
30
,
20
,
10
}
table3
:=
[]
uint64
{
60
,
50
,
40
,
30
,
20
,
10
}
table4
:=
[]
uint64
{
100
,
90
,
80
,
70
,
60
,
50
,
40
,
30
,
20
,
10
}
getTable0
:=
pricer
.
PriceTable
()
if
!
reflect
.
DeepEqual
(
table0
,
getTable0
)
{
t
.
Fatalf
(
"returned table does not match, got %+v expected %+v"
,
getTable0
,
table0
)
}
getTable1
:=
pricer
.
PriceTable
()
if
!
reflect
.
DeepEqual
(
table1
,
getTable1
)
{
t
.
Fatalf
(
"returned table does not match, got %+v expected %+v"
,
getTable1
,
table1
)
}
getTable2
:=
pricer
.
PriceTable
()
if
!
reflect
.
DeepEqual
(
table2
,
getTable2
)
{
t
.
Fatalf
(
"returned table does not match, got %+v expected %+v"
,
getTable2
,
table2
)
}
getTable3
:=
pricer
.
PriceTable
()
if
!
reflect
.
DeepEqual
(
table3
,
getTable3
)
{
t
.
Fatalf
(
"returned table does not match, got %+v expected %+v"
,
getTable3
,
table3
)
}
getTable4
:=
pricer
.
PriceTable
()
if
!
reflect
.
DeepEqual
(
table4
,
getTable4
)
{
t
.
Fatalf
(
"returned table does not match, got %+v expected %+v"
,
getTable4
,
table4
)
}
}
func
TestPeerPrice
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
defer
store
.
Close
()
overlay
:=
swarm
.
MustParseHexAddress
(
"0000617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
peer
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
chunksByPOToPeer
:=
[]
swarm
.
Address
{
swarm
.
MustParseHexAddress
(
"05ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"95ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"c5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"f0ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"e6ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
}
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepth
(
3
))
pricer
.
SetTopology
(
kad
)
peerTable
:=
[]
uint64
{
55
,
45
,
35
,
25
,
15
}
err
:=
pricer
.
NotifyPriceTable
(
peer
,
peerTable
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
for
i
,
ch
:=
range
chunksByPOToPeer
{
getPrice
:=
pricer
.
PeerPrice
(
peer
,
ch
)
if
getPrice
!=
peerTable
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPrice, got %v expected %v"
,
getPrice
,
peerTable
[
i
])
}
}
neighborhoodPeer
:=
swarm
.
MustParseHexAddress
(
"00ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
neighborhoodPeerTable
:=
[]
uint64
{
36
,
26
,
16
,
6
}
err
=
pricer
.
NotifyPriceTable
(
neighborhoodPeer
,
neighborhoodPeerTable
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
chunksByPOToNeighborhoodPeer
:=
[]
swarm
.
Address
{
swarm
.
MustParseHexAddress
(
"95ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"55ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"35ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"10ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
}
neighborhoodPeerExpectedPrices
:=
[]
uint64
{
36
,
26
,
16
,
0
}
for
i
,
ch
:=
range
chunksByPOToNeighborhoodPeer
{
getPrice
:=
pricer
.
PeerPrice
(
neighborhoodPeer
,
ch
)
if
getPrice
!=
neighborhoodPeerExpectedPrices
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPrice, got %v expected %v"
,
getPrice
,
neighborhoodPeerExpectedPrices
[
i
])
}
}
}
func
TestPriceForPeer
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
defer
store
.
Close
()
peer
:=
swarm
.
MustParseHexAddress
(
"0000617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
overlay
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
chunksByPOToOverlay
:=
[]
swarm
.
Address
{
swarm
.
MustParseHexAddress
(
"05ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"95ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"c5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"f0ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
swarm
.
MustParseHexAddress
(
"e6ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
),
}
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepth
(
4
))
pricer
.
SetTopology
(
kad
)
defaultTable
:=
[]
uint64
{
50
,
40
,
30
,
20
,
10
}
for
i
,
ch
:=
range
chunksByPOToOverlay
{
getPrice
:=
pricer
.
PriceForPeer
(
peer
,
ch
)
if
getPrice
!=
defaultTable
[
i
]
{
t
.
Fatalf
(
"unexpected price for peer, got %v expected %v"
,
getPrice
,
defaultTable
[
i
])
}
}
neighborhoodPeer
:=
swarm
.
MustParseHexAddress
(
"e7ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
expectedPricesInNeighborhood
:=
[]
uint64
{
50
,
40
,
30
,
20
,
0
}
for
i
,
ch
:=
range
chunksByPOToOverlay
{
getPrice
:=
pricer
.
PriceForPeer
(
neighborhoodPeer
,
ch
)
if
getPrice
!=
expectedPricesInNeighborhood
[
i
]
{
t
.
Fatalf
(
"unexpected price for peer, got %v expected %v"
,
getPrice
,
expectedPricesInNeighborhood
[
i
])
}
}
}
func
TestNotifyPriceTable
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
overlay
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
defer
store
.
Close
()
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepth
(
0
))
pricer
.
SetTopology
(
kad
)
peer
:=
swarm
.
MustParseHexAddress
(
"ffff617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
peerTable
:=
[]
uint64
{
66
,
55
,
44
,
33
,
22
,
11
}
err
:=
pricer
.
NotifyPriceTable
(
peer
,
peerTable
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
for
i
:=
0
;
i
<
len
(
peerTable
);
i
++
{
getPrice
,
err
:=
pricer
.
PeerPricePO
(
peer
,
uint8
(
i
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
getPrice
!=
peerTable
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPricePO, got %v expected %v"
,
getPrice
,
peerTable
[
i
])
}
}
}
func
TestNotifyPeerPrice
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
overlay
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
defer
store
.
Close
()
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepth
(
0
))
pricer
.
SetTopology
(
kad
)
peer
:=
swarm
.
MustParseHexAddress
(
"ffff617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
peerTable
:=
[]
uint64
{
33
,
22
,
11
}
err
:=
pricer
.
NotifyPriceTable
(
peer
,
peerTable
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
for
i
:=
0
;
i
<
len
(
peerTable
);
i
++
{
getPrice
,
err
:=
pricer
.
PeerPricePO
(
peer
,
uint8
(
i
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
getPrice
!=
peerTable
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPricePO, got %v expected %v"
,
getPrice
,
peerTable
[
i
])
}
}
err
=
pricer
.
NotifyPeerPrice
(
peer
,
48
,
8
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expectedTable
:=
[]
uint64
{
33
,
22
,
11
,
98
,
88
,
78
,
68
,
58
,
48
}
for
i
:=
0
;
i
<
len
(
expectedTable
);
i
++
{
getPrice
,
err
:=
pricer
.
PeerPricePO
(
peer
,
uint8
(
i
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
getPrice
!=
expectedTable
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPricePO, got %v expected %v"
,
getPrice
,
expectedTable
[
i
])
}
}
err
=
pricer
.
NotifyPeerPrice
(
peer
,
43
,
9
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expectedTable
=
[]
uint64
{
33
,
22
,
11
,
98
,
88
,
78
,
68
,
58
,
48
,
43
}
for
i
:=
0
;
i
<
len
(
expectedTable
);
i
++
{
getPrice
,
err
:=
pricer
.
PeerPricePO
(
peer
,
uint8
(
i
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
getPrice
!=
expectedTable
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPricePO, got %v expected %v"
,
getPrice
,
expectedTable
[
i
])
}
}
err
=
pricer
.
NotifyPeerPrice
(
peer
,
60
,
5
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expectedTable
=
[]
uint64
{
33
,
22
,
11
,
98
,
88
,
60
,
68
,
58
,
48
,
43
}
for
i
:=
0
;
i
<
len
(
expectedTable
);
i
++
{
getPrice
,
err
:=
pricer
.
PeerPricePO
(
peer
,
uint8
(
i
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
getPrice
!=
expectedTable
[
i
]
{
t
.
Fatalf
(
"unexpected PeerPricePO, got %v expected %v"
,
getPrice
,
expectedTable
[
i
])
}
}
}
func
TestPricerHeadler
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
overlay
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
defer
store
.
Close
()
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepth
(
2
))
pricer
.
SetTopology
(
kad
)
peer
:=
swarm
.
MustParseHexAddress
(
"07e0d4ba628ad700fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
chunkAddress
:=
swarm
.
MustParseHexAddress
(
"7a22589362e34efdd7e0d4ba628ad7007a22589362e34efdd7e0d4ba628ad700"
)
requestHeaders
,
err
:=
headerutils
.
MakePricingHeaders
(
50
,
chunkAddress
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
responseHeaders
:=
pricer
.
PriceHeadler
(
requestHeaders
,
peer
)
if
!
reflect
.
DeepEqual
(
requestHeaders
[
"target"
],
responseHeaders
[
"target"
])
{
t
.
Fatalf
(
"targets don't match, got %v, want %v"
,
responseHeaders
[
"target"
],
requestHeaders
[
"target"
])
}
chunkPriceInRequest
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
chunkPriceInRequest
,
uint64
(
50
))
chunkPriceInResponse
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
chunkPriceInResponse
,
uint64
(
30
))
if
!
reflect
.
DeepEqual
(
requestHeaders
[
"price"
],
chunkPriceInRequest
)
{
t
.
Fatalf
(
"targets don't match, got %v, want %v"
,
responseHeaders
[
"price"
],
chunkPriceInRequest
)
}
if
!
reflect
.
DeepEqual
(
responseHeaders
[
"price"
],
chunkPriceInResponse
)
{
t
.
Fatalf
(
"targets don't match, got %v, want %v"
,
responseHeaders
[
"price"
],
chunkPriceInResponse
)
}
}
func
TestPricerHeadlerBadHeaders
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
store
:=
mock
.
NewStateStore
()
overlay
:=
swarm
.
MustParseHexAddress
(
"e5ef617cadab2af7fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
defer
store
.
Close
()
pricer
:=
pricer
.
New
(
logger
,
store
,
overlay
,
10
)
kad
:=
mockkad
.
NewMockKademlia
(
mockkad
.
WithDepth
(
2
))
pricer
.
SetTopology
(
kad
)
peer
:=
swarm
.
MustParseHexAddress
(
"07e0d4ba628ad700fff48b16b52953487a22589362e34efdd7e0d4ba628ad700"
)
requestHeaders
:=
p2p
.
Headers
{
"irrelevantfield"
:
[]
byte
{},
}
responseHeaders
:=
pricer
.
PriceHeadler
(
requestHeaders
,
peer
)
if
responseHeaders
[
"target"
]
!=
nil
{
t
.
Fatal
(
"only error should be returned"
)
}
if
responseHeaders
[
"price"
]
!=
nil
{
t
.
Fatal
(
"only error should be returned"
)
}
if
responseHeaders
[
"index"
]
!=
nil
{
t
.
Fatal
(
"only error should be returned"
)
}
if
responseHeaders
[
"error"
]
==
nil
{
t
.
Fatal
(
"error should be returned"
)
}
}
pkg/pricing/pb/pricing.pb.go
View file @
3217c6e1
...
...
@@ -23,8 +23,7 @@ var _ = math.Inf
const
_
=
proto
.
GoGoProtoPackageIsVersion3
// please upgrade the proto package
type
AnnouncePaymentThreshold
struct
{
PaymentThreshold
[]
byte
`protobuf:"bytes,1,opt,name=PaymentThreshold,proto3" json:"PaymentThreshold,omitempty"`
ProximityPrice
[]
uint64
`protobuf:"varint,2,rep,packed,name=ProximityPrice,proto3" json:"ProximityPrice,omitempty"`
PaymentThreshold
[]
byte
`protobuf:"bytes,1,opt,name=PaymentThreshold,proto3" json:"PaymentThreshold,omitempty"`
}
func
(
m
*
AnnouncePaymentThreshold
)
Reset
()
{
*
m
=
AnnouncePaymentThreshold
{}
}
...
...
@@ -67,13 +66,6 @@ func (m *AnnouncePaymentThreshold) GetPaymentThreshold() []byte {
return
nil
}
func
(
m
*
AnnouncePaymentThreshold
)
GetProximityPrice
()
[]
uint64
{
if
m
!=
nil
{
return
m
.
ProximityPrice
}
return
nil
}
func
init
()
{
proto
.
RegisterType
((
*
AnnouncePaymentThreshold
)(
nil
),
"pricing.AnnouncePaymentThreshold"
)
}
...
...
@@ -81,17 +73,15 @@ func init() {
func
init
()
{
proto
.
RegisterFile
(
"pricing.proto"
,
fileDescriptor_ec4cc93d045d43d0
)
}
var
fileDescriptor_ec4cc93d045d43d0
=
[]
byte
{
// 1
50
bytes of a gzipped FileDescriptorProto
// 1
22
bytes of a gzipped FileDescriptorProto
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0xff
,
0xe2
,
0xe2
,
0x2d
,
0x28
,
0xca
,
0x4c
,
0xce
,
0xcc
,
0x4b
,
0xd7
,
0x2b
,
0x28
,
0xca
,
0x2f
,
0xc9
,
0x17
,
0x62
,
0x87
,
0x72
,
0x95
,
0x
f2
,
0xb8
,
0xce
,
0xcc
,
0x4b
,
0xd7
,
0x2b
,
0x28
,
0xca
,
0x2f
,
0xc9
,
0x17
,
0x62
,
0x87
,
0x72
,
0x95
,
0x
dc
,
0xb8
,
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
,
0x18
,
0x15
,
0x18
,
0x35
,
0x78
,
0x82
,
0x30
,
0xc4
,
0x85
,
0xd4
,
0xb8
,
0xf8
,
0x02
,
0x8a
,
0xf2
,
0x2b
,
0x32
,
0x73
,
0x33
,
0x4b
,
0x2a
,
0x03
,
0x8a
,
0x32
,
0x93
,
0x53
,
0x25
,
0x98
,
0x14
,
0x98
,
0x35
,
0x58
,
0x82
,
0xd0
,
0x44
,
0x9d
,
0x64
,
0x4e
,
0x3c
,
0x92
,
0x63
,
0xbc
,
0xf0
,
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
,
0xec
,
0x3a
,
0x63
,
0x40
,
0x00
,
0x00
,
0x00
,
0xff
,
0xff
,
0x90
,
0x49
,
0x1c
,
0x6f
,
0xae
,
0x00
,
0x00
,
0x00
,
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
,
0xf1
,
0x58
,
0x8e
,
0x21
,
0x8a
,
0xa9
,
0x20
,
0x29
,
0x89
,
0x0d
,
0x6c
,
0xab
,
0x31
,
0x20
,
0x00
,
0x00
,
0xff
,
0xff
,
0x50
,
0xca
,
0x0e
,
0x0a
,
0x86
,
0x00
,
0x00
,
0x00
,
}
func
(
m
*
AnnouncePaymentThreshold
)
Marshal
()
(
dAtA
[]
byte
,
err
error
)
{
...
...
@@ -114,24 +104,6 @@ func (m *AnnouncePaymentThreshold) MarshalToSizedBuffer(dAtA []byte) (int, error
_
=
i
var
l
int
_
=
l
if
len
(
m
.
ProximityPrice
)
>
0
{
dAtA2
:=
make
([]
byte
,
len
(
m
.
ProximityPrice
)
*
10
)
var
j1
int
for
_
,
num
:=
range
m
.
ProximityPrice
{
for
num
>=
1
<<
7
{
dAtA2
[
j1
]
=
uint8
(
uint64
(
num
)
&
0x7f
|
0x80
)
num
>>=
7
j1
++
}
dAtA2
[
j1
]
=
uint8
(
num
)
j1
++
}
i
-=
j1
copy
(
dAtA
[
i
:
],
dAtA2
[
:
j1
])
i
=
encodeVarintPricing
(
dAtA
,
i
,
uint64
(
j1
))
i
--
dAtA
[
i
]
=
0x12
}
if
len
(
m
.
PaymentThreshold
)
>
0
{
i
-=
len
(
m
.
PaymentThreshold
)
copy
(
dAtA
[
i
:
],
m
.
PaymentThreshold
)
...
...
@@ -163,13 +135,6 @@ func (m *AnnouncePaymentThreshold) Size() (n int) {
if
l
>
0
{
n
+=
1
+
l
+
sovPricing
(
uint64
(
l
))
}
if
len
(
m
.
ProximityPrice
)
>
0
{
l
=
0
for
_
,
e
:=
range
m
.
ProximityPrice
{
l
+=
sovPricing
(
uint64
(
e
))
}
n
+=
1
+
sovPricing
(
uint64
(
l
))
+
l
}
return
n
}
...
...
@@ -242,82 +207,6 @@ func (m *AnnouncePaymentThreshold) Unmarshal(dAtA []byte) error {
m
.
PaymentThreshold
=
[]
byte
{}
}
iNdEx
=
postIndex
case
2
:
if
wireType
==
0
{
var
v
uint64
for
shift
:=
uint
(
0
);
;
shift
+=
7
{
if
shift
>=
64
{
return
ErrIntOverflowPricing
}
if
iNdEx
>=
l
{
return
io
.
ErrUnexpectedEOF
}
b
:=
dAtA
[
iNdEx
]
iNdEx
++
v
|=
uint64
(
b
&
0x7F
)
<<
shift
if
b
<
0x80
{
break
}
}
m
.
ProximityPrice
=
append
(
m
.
ProximityPrice
,
v
)
}
else
if
wireType
==
2
{
var
packedLen
int
for
shift
:=
uint
(
0
);
;
shift
+=
7
{
if
shift
>=
64
{
return
ErrIntOverflowPricing
}
if
iNdEx
>=
l
{
return
io
.
ErrUnexpectedEOF
}
b
:=
dAtA
[
iNdEx
]
iNdEx
++
packedLen
|=
int
(
b
&
0x7F
)
<<
shift
if
b
<
0x80
{
break
}
}
if
packedLen
<
0
{
return
ErrInvalidLengthPricing
}
postIndex
:=
iNdEx
+
packedLen
if
postIndex
<
0
{
return
ErrInvalidLengthPricing
}
if
postIndex
>
l
{
return
io
.
ErrUnexpectedEOF
}
var
elementCount
int
var
count
int
for
_
,
integer
:=
range
dAtA
[
iNdEx
:
postIndex
]
{
if
integer
<
128
{
count
++
}
}
elementCount
=
count
if
elementCount
!=
0
&&
len
(
m
.
ProximityPrice
)
==
0
{
m
.
ProximityPrice
=
make
([]
uint64
,
0
,
elementCount
)
}
for
iNdEx
<
postIndex
{
var
v
uint64
for
shift
:=
uint
(
0
);
;
shift
+=
7
{
if
shift
>=
64
{
return
ErrIntOverflowPricing
}
if
iNdEx
>=
l
{
return
io
.
ErrUnexpectedEOF
}
b
:=
dAtA
[
iNdEx
]
iNdEx
++
v
|=
uint64
(
b
&
0x7F
)
<<
shift
if
b
<
0x80
{
break
}
}
m
.
ProximityPrice
=
append
(
m
.
ProximityPrice
,
v
)
}
}
else
{
return
fmt
.
Errorf
(
"proto: wrong wireType = %d for field ProximityPrice"
,
wireType
)
}
default
:
iNdEx
=
preIndex
skippy
,
err
:=
skipPricing
(
dAtA
[
iNdEx
:
])
...
...
pkg/pricing/pb/pricing.proto
View file @
3217c6e1
...
...
@@ -10,5 +10,4 @@ option go_package = "pb";
message
AnnouncePaymentThreshold
{
bytes
PaymentThreshold
=
1
;
repeated
uint64
ProximityPrice
=
2
;
}
pkg/pricing/pricing.go
View file @
3217c6e1
...
...
@@ -13,7 +13,6 @@ import (
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/pricer"
"github.com/ethersphere/bee/pkg/pricing/pb"
"github.com/ethersphere/bee/pkg/swarm"
)
...
...
@@ -29,7 +28,6 @@ var _ Interface = (*Service)(nil)
// Interface is the main interface of the pricing protocol
type
Interface
interface
{
AnnouncePaymentThreshold
(
ctx
context
.
Context
,
peer
swarm
.
Address
,
paymentThreshold
*
big
.
Int
)
error
AnnouncePaymentThresholdAndPriceTable
(
ctx
context
.
Context
,
peer
swarm
.
Address
,
paymentThreshold
*
big
.
Int
)
error
}
// PriceTableObserver is used for being notified of price table updates
...
...
@@ -46,16 +44,13 @@ type Service struct {
streamer
p2p
.
Streamer
logger
logging
.
Logger
paymentThreshold
*
big
.
Int
pricer
pricer
.
Interface
paymentThresholdObserver
PaymentThresholdObserver
priceTableObserver
PriceTableObserver
}
func
New
(
streamer
p2p
.
Streamer
,
logger
logging
.
Logger
,
paymentThreshold
*
big
.
Int
,
pricer
pricer
.
Interface
)
*
Service
{
func
New
(
streamer
p2p
.
Streamer
,
logger
logging
.
Logger
,
paymentThreshold
*
big
.
Int
)
*
Service
{
return
&
Service
{
streamer
:
streamer
,
logger
:
logger
,
pricer
:
pricer
,
paymentThreshold
:
paymentThreshold
,
}
}
...
...
@@ -94,15 +89,6 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e
paymentThreshold
:=
big
.
NewInt
(
0
)
.
SetBytes
(
req
.
PaymentThreshold
)
s
.
logger
.
Tracef
(
"received payment threshold announcement from peer %v of %d"
,
p
.
Address
,
paymentThreshold
)
if
req
.
ProximityPrice
!=
nil
{
s
.
logger
.
Tracef
(
"received pricetable announcement from peer %v of %v"
,
p
.
Address
,
req
.
ProximityPrice
)
err
=
s
.
priceTableObserver
.
NotifyPriceTable
(
p
.
Address
,
req
.
ProximityPrice
)
if
err
!=
nil
{
s
.
logger
.
Debugf
(
"error receiving pricetable from peer %v: %w"
,
p
.
Address
,
err
)
s
.
logger
.
Errorf
(
"error receiving pricetable from peer %v: %w"
,
p
.
Address
,
err
)
}
}
if
paymentThreshold
.
Cmp
(
big
.
NewInt
(
0
))
==
0
{
return
err
}
...
...
@@ -110,7 +96,7 @@ func (s *Service) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream) (e
}
func
(
s
*
Service
)
init
(
ctx
context
.
Context
,
p
p2p
.
Peer
)
error
{
err
:=
s
.
AnnouncePaymentThreshold
AndPriceTable
(
ctx
,
p
.
Address
,
s
.
paymentThreshold
)
err
:=
s
.
AnnouncePaymentThreshold
(
ctx
,
p
.
Address
,
s
.
paymentThreshold
)
if
err
!=
nil
{
s
.
logger
.
Warningf
(
"could not send payment threshold announcement to peer %v"
,
p
.
Address
)
}
...
...
@@ -143,39 +129,7 @@ func (s *Service) AnnouncePaymentThreshold(ctx context.Context, peer swarm.Addre
return
err
}
// AnnouncePaymentThresholdAndPriceTable announces own payment threshold and pricetable to peer
func
(
s
*
Service
)
AnnouncePaymentThresholdAndPriceTable
(
ctx
context
.
Context
,
peer
swarm
.
Address
,
paymentThreshold
*
big
.
Int
)
error
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
5
*
time
.
Second
)
defer
cancel
()
stream
,
err
:=
s
.
streamer
.
NewStream
(
ctx
,
peer
,
nil
,
protocolName
,
protocolVersion
,
streamName
)
if
err
!=
nil
{
return
err
}
defer
func
()
{
if
err
!=
nil
{
_
=
stream
.
Reset
()
}
else
{
go
stream
.
FullClose
()
}
}()
s
.
logger
.
Tracef
(
"sending payment threshold announcement to peer %v of %d"
,
peer
,
paymentThreshold
)
w
:=
protobuf
.
NewWriter
(
stream
)
err
=
w
.
WriteMsgWithContext
(
ctx
,
&
pb
.
AnnouncePaymentThreshold
{
PaymentThreshold
:
paymentThreshold
.
Bytes
(),
ProximityPrice
:
s
.
pricer
.
PriceTable
(),
})
return
err
}
// SetPaymentThresholdObserver sets the PaymentThresholdObserver to be used when receiving a new payment threshold
func
(
s
*
Service
)
SetPaymentThresholdObserver
(
observer
PaymentThresholdObserver
)
{
s
.
paymentThresholdObserver
=
observer
}
// SetPriceTableObserver sets the PriceTableObserver to be used when receiving a new pricetable
func
(
s
*
Service
)
SetPriceTableObserver
(
observer
PriceTableObserver
)
{
s
.
priceTableObserver
=
observer
}
pkg/pricing/pricing_test.go
View file @
3217c6e1
...
...
@@ -9,13 +9,11 @@ import (
"context"
"io/ioutil"
"math/big"
"reflect"
"testing"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/p2p/streamtest"
pricermock
"github.com/ethersphere/bee/pkg/pricer/mock"
"github.com/ethersphere/bee/pkg/pricing"
"github.com/ethersphere/bee/pkg/pricing/pb"
"github.com/ethersphere/bee/pkg/swarm"
...
...
@@ -27,12 +25,6 @@ type testThresholdObserver struct {
paymentThreshold
*
big
.
Int
}
type
testPriceTableObserver
struct
{
called
bool
peer
swarm
.
Address
priceTable
[]
uint64
}
func
(
t
*
testThresholdObserver
)
NotifyPaymentThreshold
(
peerAddr
swarm
.
Address
,
paymentThreshold
*
big
.
Int
)
error
{
t
.
called
=
true
t
.
peer
=
peerAddr
...
...
@@ -40,21 +32,12 @@ func (t *testThresholdObserver) NotifyPaymentThreshold(peerAddr swarm.Address, p
return
nil
}
func
(
t
*
testPriceTableObserver
)
NotifyPriceTable
(
peerAddr
swarm
.
Address
,
priceTable
[]
uint64
)
error
{
t
.
called
=
true
t
.
peer
=
peerAddr
t
.
priceTable
=
priceTable
return
nil
}
func
TestAnnouncePaymentThreshold
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
testThreshold
:=
big
.
NewInt
(
100000
)
observer
:=
&
testThresholdObserver
{}
pricerMockService
:=
pricermock
.
NewMockService
()
recipient
:=
pricing
.
New
(
nil
,
logger
,
testThreshold
,
pricerMockService
)
recipient
:=
pricing
.
New
(
nil
,
logger
,
testThreshold
)
recipient
.
SetPaymentThresholdObserver
(
observer
)
peerID
:=
swarm
.
MustParseHexAddress
(
"9ee7add7"
)
...
...
@@ -64,7 +47,7 @@ func TestAnnouncePaymentThreshold(t *testing.T) {
streamtest
.
WithBaseAddr
(
peerID
),
)
payer
:=
pricing
.
New
(
recorder
,
logger
,
testThreshold
,
pricerMockService
)
payer
:=
pricing
.
New
(
recorder
,
logger
,
testThreshold
)
paymentThreshold
:=
big
.
NewInt
(
10000
)
...
...
@@ -113,93 +96,3 @@ func TestAnnouncePaymentThreshold(t *testing.T) {
t
.
Fatalf
(
"observer called with wrong peer. got %v, want %v"
,
observer
.
peer
,
peerID
)
}
}
func
TestAnnouncePaymentThresholdAndPriceTable
(
t
*
testing
.
T
)
{
logger
:=
logging
.
New
(
ioutil
.
Discard
,
0
)
testThreshold
:=
big
.
NewInt
(
100000
)
observer1
:=
&
testThresholdObserver
{}
observer2
:=
&
testPriceTableObserver
{}
table
:=
[]
uint64
{
50
,
25
,
12
,
6
}
priceTableFunc
:=
func
()
[]
uint64
{
return
table
}
pricerMockService
:=
pricermock
.
NewMockService
(
pricermock
.
WithPriceTableFunc
(
priceTableFunc
))
recipient
:=
pricing
.
New
(
nil
,
logger
,
testThreshold
,
pricerMockService
)
recipient
.
SetPaymentThresholdObserver
(
observer1
)
recipient
.
SetPriceTableObserver
(
observer2
)
peerID
:=
swarm
.
MustParseHexAddress
(
"9ee7add7"
)
recorder
:=
streamtest
.
New
(
streamtest
.
WithProtocols
(
recipient
.
Protocol
()),
streamtest
.
WithBaseAddr
(
peerID
),
)
payer
:=
pricing
.
New
(
recorder
,
logger
,
testThreshold
,
pricerMockService
)
paymentThreshold
:=
big
.
NewInt
(
10000
)
err
:=
payer
.
AnnouncePaymentThresholdAndPriceTable
(
context
.
Background
(),
peerID
,
paymentThreshold
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
records
,
err
:=
recorder
.
Records
(
peerID
,
"pricing"
,
"1.0.0"
,
"pricing"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
l
:=
len
(
records
);
l
!=
1
{
t
.
Fatalf
(
"got %v records, want %v"
,
l
,
1
)
}
record
:=
records
[
0
]
messages
,
err
:=
protobuf
.
ReadMessages
(
bytes
.
NewReader
(
record
.
In
()),
func
()
protobuf
.
Message
{
return
new
(
pb
.
AnnouncePaymentThreshold
)
},
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
len
(
messages
)
!=
1
{
t
.
Fatalf
(
"got %v messages, want %v"
,
len
(
messages
),
1
)
}
sentPaymentThreshold
:=
big
.
NewInt
(
0
)
.
SetBytes
(
messages
[
0
]
.
(
*
pb
.
AnnouncePaymentThreshold
)
.
PaymentThreshold
)
if
sentPaymentThreshold
.
Cmp
(
paymentThreshold
)
!=
0
{
t
.
Fatalf
(
"got message with amount %v, want %v"
,
sentPaymentThreshold
,
paymentThreshold
)
}
sentPriceTable
:=
messages
[
0
]
.
(
*
pb
.
AnnouncePaymentThreshold
)
.
ProximityPrice
if
!
reflect
.
DeepEqual
(
sentPriceTable
,
table
)
{
t
.
Fatalf
(
"got message with table %v, want %v"
,
sentPriceTable
,
table
)
}
if
!
observer1
.
called
{
t
.
Fatal
(
"expected threshold observer to be called"
)
}
if
observer1
.
paymentThreshold
.
Cmp
(
paymentThreshold
)
!=
0
{
t
.
Fatalf
(
"observer called with wrong paymentThreshold. got %d, want %d"
,
observer1
.
paymentThreshold
,
paymentThreshold
)
}
if
!
observer1
.
peer
.
Equal
(
peerID
)
{
t
.
Fatalf
(
"threshold observer called with wrong peer. got %v, want %v"
,
observer1
.
peer
,
peerID
)
}
if
!
observer2
.
called
{
t
.
Fatal
(
"expected table observer to be called"
)
}
if
!
reflect
.
DeepEqual
(
observer2
.
priceTable
,
table
)
{
t
.
Fatalf
(
"table observer called with wrong priceTable. got %d, want %d"
,
observer2
.
priceTable
,
table
)
}
if
!
observer2
.
peer
.
Equal
(
peerID
)
{
t
.
Fatalf
(
"table observer called with wrong peer. got %v, want %v"
,
observer2
.
peer
,
peerID
)
}
}
pkg/pushsync/pushsync.go
View file @
3217c6e1
...
...
@@ -19,7 +19,6 @@ import (
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/pricer"
"github.com/ethersphere/bee/pkg/pricer/headerutils"
"github.com/ethersphere/bee/pkg/pushsync/pb"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/storage"
...
...
@@ -98,7 +97,6 @@ func (s *PushSync) Protocol() p2p.ProtocolSpec {
{
Name
:
streamName
,
Handler
:
s
.
handler
,
Headler
:
s
.
pricer
.
PriceHeadler
,
},
},
}
...
...
@@ -134,14 +132,7 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
return
swarm
.
ErrInvalidChunk
}
// Get price we charge for upstream peer read at headler.
responseHeaders
:=
stream
.
ResponseHeaders
()
price
,
err
:=
headerutils
.
ParsePriceHeader
(
responseHeaders
)
// if not found in returned header, compute the price we charge for this chunk.
if
err
!=
nil
{
ps
.
logger
.
Warningf
(
"pushsync: peer %v no price in previously issued response headers: %v"
,
p
.
Address
,
err
)
price
=
ps
.
pricer
.
PriceForPeer
(
p
.
Address
,
chunk
.
Address
())
}
price
:=
ps
.
pricer
.
Price
(
chunk
.
Address
())
// if the peer is closer to the chunk, we were selected for replication. Return early.
if
dcmp
,
_
:=
swarm
.
DistanceCmp
(
chunk
.
Address
()
.
Bytes
(),
p
.
Address
.
Bytes
(),
ps
.
address
.
Bytes
());
dcmp
==
1
{
...
...
@@ -153,6 +144,8 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
return
ps
.
accounting
.
Debit
(
p
.
Address
,
price
)
}
fmt
.
Println
(
"YAY"
)
fmt
.
Println
(
ps
.
address
)
return
ErrOutOfDepthReplication
}
...
...
@@ -204,34 +197,22 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
}()
// price for neighborhood replication
const
receiptPrice
uint64
=
0
receiptPrice
:=
ps
.
pricer
.
PeerPrice
(
peer
,
chunk
.
Address
())
headers
,
err
:=
headerutils
.
MakePricingHeaders
(
receiptPrice
,
chunk
.
Address
()
)
err
=
ps
.
accounting
.
Reserve
(
ctx
,
peer
,
receiptPrice
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"
make pricing headers: %w"
,
err
)
err
=
fmt
.
Errorf
(
"
reserve balance for peer %s: %w"
,
peer
.
String
()
,
err
)
return
}
defer
ps
.
accounting
.
Release
(
peer
,
receiptPrice
)
streamer
,
err
:=
ps
.
streamer
.
NewStream
(
ctx
,
peer
,
headers
,
protocolName
,
protocolVersion
,
streamName
)
streamer
,
err
:=
ps
.
streamer
.
NewStream
(
ctx
,
peer
,
nil
,
protocolName
,
protocolVersion
,
streamName
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"new stream for peer %s: %w"
,
peer
.
String
(),
err
)
return
}
defer
streamer
.
Close
()
returnedHeaders
:=
streamer
.
Headers
()
_
,
returnedPrice
,
returnedIndex
,
err
:=
headerutils
.
ParsePricingResponseHeaders
(
returnedHeaders
)
if
err
!=
nil
{
err
=
fmt
.
Errorf
(
"push price headers read returned: %w"
,
err
)
return
}
// check if returned price matches presumed price, if not, return early.
if
returnedPrice
!=
receiptPrice
{
err
=
ps
.
pricer
.
NotifyPeerPrice
(
peer
,
returnedPrice
,
returnedIndex
)
return
}
w
:=
protobuf
.
NewWriter
(
streamer
)
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
timeToWaitForPushsyncToNeighbor
)
defer
cancel
()
...
...
@@ -245,6 +226,8 @@ func (ps *PushSync) handler(ctx context.Context, p p2p.Peer, stream p2p.Stream)
return
}
_
=
ps
.
accounting
.
Credit
(
peer
,
receiptPrice
)
}(
peer
)
return
false
,
false
,
nil
...
...
@@ -341,34 +324,14 @@ func (ps *PushSync) pushToClosest(ctx context.Context, ch swarm.Chunk) (rr *pb.R
// compute the price we pay for this receipt and reserve it for the rest of this function
receiptPrice
:=
ps
.
pricer
.
PeerPrice
(
peer
,
ch
.
Address
())
headers
,
err
:=
headerutils
.
MakePricingHeaders
(
receiptPrice
,
ch
.
Address
())
if
err
!=
nil
{
return
nil
,
err
}
streamer
,
err
:=
ps
.
streamer
.
NewStream
(
ctx
,
peer
,
headers
,
protocolName
,
protocolVersion
,
streamName
)
streamer
,
err
:=
ps
.
streamer
.
NewStream
(
ctx
,
peer
,
nil
,
protocolName
,
protocolVersion
,
streamName
)
if
err
!=
nil
{
lastErr
=
fmt
.
Errorf
(
"new stream for peer %s: %w"
,
peer
.
String
(),
err
)
continue
}
deferFuncs
=
append
(
deferFuncs
,
func
()
{
go
streamer
.
FullClose
()
})
returnedHeaders
:=
streamer
.
Headers
()
_
,
returnedPrice
,
returnedIndex
,
err
:=
headerutils
.
ParsePricingResponseHeaders
(
returnedHeaders
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"push price headers: read returned: %w"
,
err
)
}
// check if returned price matches presumed price, if not, update price
if
returnedPrice
!=
receiptPrice
{
err
=
ps
.
pricer
.
NotifyPeerPrice
(
peer
,
returnedPrice
,
returnedIndex
)
// save priceHeaders["price"] corresponding row for peer
if
err
!=
nil
{
return
nil
,
err
}
receiptPrice
=
returnedPrice
}
// Reserve to see whether we can make the request based on actual price
// Reserve to see whether we can make the request
err
=
ps
.
accounting
.
Reserve
(
ctx
,
peer
,
receiptPrice
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"reserve balance for peer %s: %w"
,
peer
.
String
(),
err
)
...
...
pkg/pushsync/pushsync_test.go
View file @
3217c6e1
...
...
@@ -22,7 +22,6 @@ import (
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/p2p/streamtest"
"github.com/ethersphere/bee/pkg/pricer/headerutils"
pricermock
"github.com/ethersphere/bee/pkg/pricer/mock"
"github.com/ethersphere/bee/pkg/pushsync"
"github.com/ethersphere/bee/pkg/pushsync/pb"
...
...
@@ -107,65 +106,6 @@ func TestSendChunkAndReceiveReceipt(t *testing.T) {
}
}
func
TestSendChunkAfterPriceUpdate
(
t
*
testing
.
T
)
{
// chunk data to upload
chunk
:=
testingc
.
FixtureChunk
(
"7000"
)
// create a pivot node and a mocked closest node
pivotNode
:=
swarm
.
MustParseHexAddress
(
"0000000000000000000000000000000000000000000000000000000000000000"
)
// base is 0000
closestPeer
:=
swarm
.
MustParseHexAddress
(
"6000000000000000000000000000000000000000000000000000000000000000"
)
// binary 0110 -> po 1
// peer is the node responding to the chunk receipt message
// mock should return ErrWantSelf since there's no one to forward to
serverPrice
:=
uint64
(
17
)
serverPrices
:=
pricerParameters
{
price
:
serverPrice
,
peerPrice
:
fixedPrice
}
psPeer
,
storerPeer
,
_
,
peerAccounting
:=
createPushSyncNode
(
t
,
closestPeer
,
serverPrices
,
nil
,
nil
,
defaultSigner
,
mock
.
WithClosestPeerErr
(
topology
.
ErrWantSelf
))
defer
storerPeer
.
Close
()
recorder
:=
streamtest
.
New
(
streamtest
.
WithProtocols
(
psPeer
.
Protocol
()),
streamtest
.
WithBaseAddr
(
pivotNode
))
// pivot node needs the streamer since the chunk is intercepted by
// the chunk worker, then gets sent by opening a new stream
psPivot
,
storerPivot
,
_
,
pivotAccounting
:=
createPushSyncNode
(
t
,
pivotNode
,
defaultPrices
,
recorder
,
nil
,
defaultSigner
,
mock
.
WithClosestPeer
(
closestPeer
))
defer
storerPivot
.
Close
()
// Trigger the sending of chunk to the closest node
receipt
,
err
:=
psPivot
.
PushChunkToClosest
(
context
.
Background
(),
chunk
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
chunk
.
Address
()
.
Equal
(
receipt
.
Address
)
{
t
.
Fatal
(
"invalid receipt"
)
}
// this intercepts the outgoing delivery message
waitOnRecordAndTest
(
t
,
closestPeer
,
recorder
,
chunk
.
Address
(),
chunk
.
Data
())
// this intercepts the incoming receipt message
waitOnRecordAndTest
(
t
,
closestPeer
,
recorder
,
chunk
.
Address
(),
nil
)
balance
,
err
:=
pivotAccounting
.
Balance
(
closestPeer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
balance
.
Int64
()
!=
-
int64
(
serverPrice
)
{
t
.
Fatalf
(
"unexpected balance on pivot. want %d got %d"
,
-
int64
(
serverPrice
),
balance
)
}
balance
,
err
=
peerAccounting
.
Balance
(
pivotNode
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
balance
.
Int64
()
!=
int64
(
serverPrice
)
{
t
.
Fatalf
(
"unexpected balance on peer. want %d got %d"
,
int64
(
serverPrice
),
balance
)
}
}
// TestReplicateBeforeReceipt tests that a chunk is pushed and a receipt is received.
// Also the storer node initiates a pushsync to N closest nodes of the chunk as it's sending back the receipt.
// The second storer should only store it and not forward it. The balance of all nodes is tested.
...
...
@@ -174,8 +114,6 @@ func TestReplicateBeforeReceipt(t *testing.T) {
// chunk data to upload
chunk
:=
testingc
.
FixtureChunk
(
"7000"
)
// base 0111
neighborPrice
:=
pricerParameters
{
price
:
0
,
peerPrice
:
0
}
// create a pivot node and a mocked closest node
pivotNode
:=
swarm
.
MustParseHexAddress
(
"0000000000000000000000000000000000000000000000000000000000000000"
)
// base is 0000
closestPeer
:=
swarm
.
MustParseHexAddress
(
"6000000000000000000000000000000000000000000000000000000000000000"
)
// binary 0110
...
...
@@ -187,9 +125,13 @@ func TestReplicateBeforeReceipt(t *testing.T) {
_
,
storerEmpty
,
_
,
_
:=
createPushSyncNode
(
t
,
emptyPeer
,
defaultPrices
,
nil
,
nil
,
defaultSigner
)
defer
storerEmpty
.
Close
()
wFunc
:=
func
(
addr
swarm
.
Address
)
bool
{
return
true
}
// node that is connected to closestPeer
// will receieve chunk from closestPeer
psSecond
,
storerSecond
,
_
,
secondAccounting
:=
createPushSyncNode
(
t
,
secondPeer
,
neighborPrice
,
nil
,
nil
,
defaultSigner
,
mock
.
WithPeers
(
emptyPeer
))
psSecond
,
storerSecond
,
_
,
secondAccounting
:=
createPushSyncNode
(
t
,
secondPeer
,
defaultPrices
,
nil
,
nil
,
defaultSigner
,
mock
.
WithPeers
(
emptyPeer
),
mock
.
WithIsWithinFunc
(
wFunc
))
defer
storerSecond
.
Close
()
secondRecorder
:=
streamtest
.
New
(
streamtest
.
WithProtocols
(
psSecond
.
Protocol
()),
streamtest
.
WithBaseAddr
(
closestPeer
))
...
...
@@ -253,16 +195,16 @@ func TestReplicateBeforeReceipt(t *testing.T) {
t
.
Fatal
(
err
)
}
if
balance
.
Int64
()
!=
0
{
t
.
Fatalf
(
"unexpected balance on second storer. want %d got %d"
,
0
,
balance
)
if
balance
.
Int64
()
!=
int64
(
fixedPrice
)
{
t
.
Fatalf
(
"unexpected balance on second storer. want %d got %d"
,
int64
(
fixedPrice
)
,
balance
)
}
balance
,
err
=
storerAccounting
.
Balance
(
secondPeer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
balance
.
Int64
()
!=
0
{
t
.
Fatalf
(
"unexpected balance on storer node. want %d got %d"
,
0
,
balance
)
if
balance
.
Int64
()
!=
-
int64
(
fixedPrice
)
{
t
.
Fatalf
(
"unexpected balance on storer node. want %d got %d"
,
-
int64
(
fixedPrice
)
,
balance
)
}
}
...
...
@@ -566,96 +508,6 @@ func TestHandler(t *testing.T) {
}
}
func
TestHandlerWithUpdate
(
t
*
testing
.
T
)
{
// chunk data to upload
chunk
:=
testingc
.
FixtureChunk
(
"7000"
)
serverPrice
:=
uint64
(
17
)
serverPrices
:=
pricerParameters
{
price
:
serverPrice
,
peerPrice
:
fixedPrice
}
// create a pivot node and a mocked closest node
triggerPeer
:=
swarm
.
MustParseHexAddress
(
"0000000000000000000000000000000000000000000000000000000000000000"
)
pivotPeer
:=
swarm
.
MustParseHexAddress
(
"5000000000000000000000000000000000000000000000000000000000000000"
)
closestPeer
:=
swarm
.
MustParseHexAddress
(
"6000000000000000000000000000000000000000000000000000000000000000"
)
// Create the closest peer with default prices (10)
psClosestPeer
,
closestStorerPeerDB
,
_
,
closestAccounting
:=
createPushSyncNode
(
t
,
closestPeer
,
defaultPrices
,
nil
,
nil
,
defaultSigner
,
mock
.
WithClosestPeerErr
(
topology
.
ErrWantSelf
))
defer
closestStorerPeerDB
.
Close
()
closestRecorder
:=
streamtest
.
New
(
streamtest
.
WithProtocols
(
psClosestPeer
.
Protocol
()),
streamtest
.
WithBaseAddr
(
pivotPeer
))
// creating the pivot peer who will act as a forwarder node with a higher price (17)
psPivot
,
storerPivotDB
,
_
,
pivotAccounting
:=
createPushSyncNode
(
t
,
pivotPeer
,
serverPrices
,
closestRecorder
,
nil
,
defaultSigner
,
mock
.
WithClosestPeer
(
closestPeer
))
defer
storerPivotDB
.
Close
()
pivotRecorder
:=
streamtest
.
New
(
streamtest
.
WithProtocols
(
psPivot
.
Protocol
()),
streamtest
.
WithBaseAddr
(
triggerPeer
))
// Creating the trigger peer with default price (10)
psTriggerPeer
,
triggerStorerDB
,
_
,
triggerAccounting
:=
createPushSyncNode
(
t
,
triggerPeer
,
defaultPrices
,
pivotRecorder
,
nil
,
defaultSigner
,
mock
.
WithClosestPeer
(
pivotPeer
))
defer
triggerStorerDB
.
Close
()
receipt
,
err
:=
psTriggerPeer
.
PushChunkToClosest
(
context
.
Background
(),
chunk
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
chunk
.
Address
()
.
Equal
(
receipt
.
Address
)
{
t
.
Fatal
(
"invalid receipt"
)
}
// In pivot peer, intercept the incoming delivery chunk from the trigger peer and check for correctness
waitOnRecordAndTest
(
t
,
pivotPeer
,
pivotRecorder
,
chunk
.
Address
(),
chunk
.
Data
())
// Pivot peer will forward the chunk to its closest peer. Intercept the incoming stream from pivot node and check
// for the correctness of the chunk
waitOnRecordAndTest
(
t
,
closestPeer
,
closestRecorder
,
chunk
.
Address
(),
chunk
.
Data
())
// Similarly intercept the same incoming stream to see if the closest peer is sending a proper receipt
waitOnRecordAndTest
(
t
,
closestPeer
,
closestRecorder
,
chunk
.
Address
(),
nil
)
// In the received stream, check if a receipt is sent from pivot peer and check for its correctness.
waitOnRecordAndTest
(
t
,
pivotPeer
,
pivotRecorder
,
chunk
.
Address
(),
nil
)
balance
,
err
:=
triggerAccounting
.
Balance
(
pivotPeer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// balance on triggering peer towards the forwarder should show negative serverPrice (17)
if
balance
.
Int64
()
!=
-
int64
(
serverPrice
)
{
t
.
Fatalf
(
"unexpected balance on trigger. want %d got %d"
,
-
int64
(
serverPrice
),
balance
)
}
// we need to check here for pivotPeer instead of triggerPeer because during streamtest the peer in the handler is actually the receiver
// balance on forwarding peer for the triggering peer should show serverPrice (17)
balance
,
err
=
pivotAccounting
.
Balance
(
triggerPeer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
balance
.
Int64
()
!=
int64
(
serverPrice
)
{
t
.
Fatalf
(
"unexpected balance on pivot. want %d got %d"
,
int64
(
serverPrice
),
balance
)
}
balance
,
err
=
pivotAccounting
.
Balance
(
closestPeer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// balance of the forwarder peer for the closest peer should show negative default price (10)
if
balance
.
Int64
()
!=
-
int64
(
fixedPrice
)
{
t
.
Fatalf
(
"unexpected balance on pivot. want %d got %d"
,
-
int64
(
fixedPrice
),
balance
)
}
balance
,
err
=
closestAccounting
.
Balance
(
pivotPeer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// balance of the closest peer for the forwarder peer should show the default price (10)
if
balance
.
Int64
()
!=
int64
(
fixedPrice
)
{
t
.
Fatalf
(
"unexpected balance on closest. want %d got %d"
,
int64
(
fixedPrice
),
balance
)
}
}
func
TestSignsReceipt
(
t
*
testing
.
T
)
{
// chunk data to upload
...
...
@@ -711,13 +563,7 @@ func createPushSyncNode(t *testing.T, addr swarm.Address, prices pricerParameter
mtag
:=
tags
.
NewTags
(
mockStatestore
,
logger
)
mockAccounting
:=
accountingmock
.
NewAccounting
()
headlerFunc
:=
func
(
h
p2p
.
Headers
,
a
swarm
.
Address
)
p2p
.
Headers
{
target
,
_
:=
headerutils
.
ParseTargetHeader
(
h
)
headers
,
_
:=
headerutils
.
MakePricingResponseHeaders
(
prices
.
price
,
target
,
0
)
return
headers
}
mockPricer
:=
pricermock
.
NewMockService
(
pricermock
.
WithPriceHeadlerFunc
(
headlerFunc
),
pricermock
.
WithPrice
(
prices
.
price
),
pricermock
.
WithPeerPrice
(
prices
.
peerPrice
))
mockPricer
:=
pricermock
.
NewMockService
(
prices
.
price
,
prices
.
peerPrice
)
recorderDisconnecter
:=
streamtest
.
NewRecorderDisconnecter
(
recorder
)
if
unwrap
==
nil
{
...
...
pkg/recovery/repair_test.go
View file @
3217c6e1
...
...
@@ -220,7 +220,7 @@ func newTestNetStore(t *testing.T, recoveryFunc recovery.Callback) storage.Store
mockStorer
:=
storemock
.
NewStorer
()
serverMockAccounting
:=
accountingmock
.
NewAccounting
()
pricerMock
:=
pricermock
.
NewMockService
()
pricerMock
:=
pricermock
.
NewMockService
(
10
,
10
)
peerID
:=
swarm
.
MustParseHexAddress
(
"deadbeef"
)
ps
:=
mockPeerSuggester
{
eachPeerRevFunc
:
func
(
f
topology
.
EachPeerFunc
)
error
{
_
,
_
,
_
=
f
(
peerID
,
0
)
...
...
pkg/retrieval/retrieval.go
View file @
3217c6e1
...
...
@@ -21,7 +21,6 @@ import (
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/pricer"
"github.com/ethersphere/bee/pkg/pricer/headerutils"
pb
"github.com/ethersphere/bee/pkg/retrieval/pb"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/storage"
...
...
@@ -81,7 +80,6 @@ func (s *Service) Protocol() p2p.ProtocolSpec {
{
Name
:
streamName
,
Handler
:
s
.
handler
,
Headler
:
s
.
pricer
.
PriceHeadler
,
},
},
}
...
...
@@ -204,23 +202,16 @@ func (s *Service) retrieveChunk(ctx context.Context, addr swarm.Address, sp *ski
sp
.
Add
(
peer
)
// compute the p
rice we presume to pay
for this chunk for price header
// compute the p
eer's price
for this chunk for price header
chunkPrice
:=
s
.
pricer
.
PeerPrice
(
peer
,
addr
)
headers
,
err
:=
headerutils
.
MakePricingHeaders
(
chunkPrice
,
addr
)
if
err
!=
nil
{
return
nil
,
swarm
.
Address
{},
err
}
s
.
logger
.
Tracef
(
"retrieval: requesting chunk %s from peer %s"
,
addr
,
peer
)
stream
,
err
:=
s
.
streamer
.
NewStream
(
ctx
,
peer
,
headers
,
protocolName
,
protocolVersion
,
streamName
)
stream
,
err
:=
s
.
streamer
.
NewStream
(
ctx
,
peer
,
nil
,
protocolName
,
protocolVersion
,
streamName
)
if
err
!=
nil
{
s
.
metrics
.
TotalErrors
.
Inc
()
return
nil
,
peer
,
fmt
.
Errorf
(
"new stream: %w"
,
err
)
}
returnedHeaders
:=
stream
.
Headers
()
defer
func
()
{
if
err
!=
nil
{
_
=
stream
.
Reset
()
...
...
@@ -229,21 +220,7 @@ func (s *Service) retrieveChunk(ctx context.Context, addr swarm.Address, sp *ski
}
}()
_
,
returnedPrice
,
returnedIndex
,
err
:=
headerutils
.
ParsePricingResponseHeaders
(
returnedHeaders
)
if
err
!=
nil
{
return
nil
,
peer
,
fmt
.
Errorf
(
"retrieval headers: read returned: %w"
,
err
)
}
// check if returned price matches presumed price, if not, update price
if
returnedPrice
!=
chunkPrice
{
err
=
s
.
pricer
.
NotifyPeerPrice
(
peer
,
returnedPrice
,
returnedIndex
)
// save priceHeaders["price"] corresponding row for peer
if
err
!=
nil
{
return
nil
,
peer
,
err
}
chunkPrice
=
returnedPrice
}
// Reserve to see whether we can request the chunk based on actual price
// Reserve to see whether we can request the chunk
err
=
s
.
accounting
.
Reserve
(
ctx
,
peer
,
chunkPrice
)
if
err
!=
nil
{
return
nil
,
peer
,
err
...
...
@@ -383,15 +360,8 @@ 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
())
// to get price Read in headler,
returnedHeaders
:=
stream
.
ResponseHeaders
()
chunkPrice
,
err
:=
headerutils
.
ParsePriceHeader
(
returnedHeaders
)
chunkPrice
:=
s
.
pricer
.
Price
(
chunk
.
Address
())
if
err
!=
nil
{
// if not found in returned header, compute the price we charge for this chunk and
s
.
logger
.
Warningf
(
"retrieval: peer %v no price in previously issued response headers: %v"
,
p
.
Address
,
err
)
chunkPrice
=
s
.
pricer
.
PriceForPeer
(
p
.
Address
,
chunk
.
Address
())
}
// debit price from p's balance
return
s
.
accounting
.
Debit
(
p
.
Address
,
chunkPrice
)
}
pkg/retrieval/retrieval_test.go
View file @
3217c6e1
...
...
@@ -11,7 +11,6 @@ import (
"errors"
"fmt"
"io/ioutil"
"math/big"
"sync"
"testing"
"time"
...
...
@@ -22,7 +21,6 @@ import (
"github.com/ethersphere/bee/pkg/p2p"
"github.com/ethersphere/bee/pkg/p2p/protobuf"
"github.com/ethersphere/bee/pkg/p2p/streamtest"
"github.com/ethersphere/bee/pkg/pricer/headerutils"
pricermock
"github.com/ethersphere/bee/pkg/pricer/mock"
"github.com/ethersphere/bee/pkg/retrieval"
pb
"github.com/ethersphere/bee/pkg/retrieval/pb"
...
...
@@ -33,17 +31,15 @@ import (
"github.com/ethersphere/bee/pkg/topology"
)
var
testTimeout
=
5
*
time
.
Second
var
(
testTimeout
=
5
*
time
.
Second
defaultPrice
=
uint64
(
10
)
)
// TestDelivery tests that a naive request -> delivery flow works.
func
TestDelivery
(
t
*
testing
.
T
)
{
var
(
chunk
=
testingc
.
FixtureChunk
(
"0033"
)
headlerFunc
=
func
(
h
p2p
.
Headers
,
a
swarm
.
Address
)
p2p
.
Headers
{
headers
,
_
:=
headerutils
.
MakePricingResponseHeaders
(
10
,
chunk
.
Address
(),
0
)
return
headers
}
chunk
=
testingc
.
FixtureChunk
(
"0033"
)
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
mockStorer
=
storemock
.
NewStorer
()
clientMockAccounting
=
accountingmock
.
NewAccounting
()
...
...
@@ -51,8 +47,7 @@ func TestDelivery(t *testing.T) {
clientAddr
=
swarm
.
MustParseHexAddress
(
"9ee7add8"
)
serverAddr
=
swarm
.
MustParseHexAddress
(
"9ee7add7"
)
price
=
uint64
(
10
)
pricerMock
=
pricermock
.
NewMockService
(
pricermock
.
WithPriceHeadlerFunc
(
headlerFunc
))
pricerMock
=
pricermock
.
NewMockService
(
defaultPrice
,
defaultPrice
)
)
// put testdata in the mock store of the server
...
...
@@ -132,136 +127,21 @@ func TestDelivery(t *testing.T) {
}
clientBalance
,
_
:=
clientMockAccounting
.
Balance
(
serverAddr
)
if
clientBalance
.
Int64
()
!=
-
int64
(
p
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
p
rice
,
clientBalance
)
if
clientBalance
.
Int64
()
!=
-
int64
(
defaultP
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
defaultP
rice
,
clientBalance
)
}
serverBalance
,
_
:=
serverMockAccounting
.
Balance
(
clientAddr
)
if
serverBalance
.
Int64
()
!=
int64
(
price
)
{
t
.
Fatalf
(
"unexpected balance on server. want %d got %d"
,
price
,
serverBalance
)
}
}
// TestDelivery tests that a naive request -> delivery flow works.
func
TestDeliveryWithPriceUpdate
(
t
*
testing
.
T
)
{
var
(
price
=
uint64
(
10
)
serverPrice
=
uint64
(
17
)
chunk
=
testingc
.
FixtureChunk
(
"0033"
)
headlerFunc
=
func
(
h
p2p
.
Headers
,
a
swarm
.
Address
)
p2p
.
Headers
{
headers
,
_
:=
headerutils
.
MakePricingResponseHeaders
(
serverPrice
,
chunk
.
Address
(),
5
)
return
headers
}
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
mockStorer
=
storemock
.
NewStorer
()
clientMockAccounting
=
accountingmock
.
NewAccounting
()
serverMockAccounting
=
accountingmock
.
NewAccounting
()
clientAddr
=
swarm
.
MustParseHexAddress
(
"9ee7add8"
)
serverAddr
=
swarm
.
MustParseHexAddress
(
"9ee7add7"
)
clientPricerMock
=
pricermock
.
NewMockService
(
pricermock
.
WithPeerPrice
(
price
))
serverPricerMock
=
pricermock
.
NewMockService
(
pricermock
.
WithPriceHeadlerFunc
(
headlerFunc
),
pricermock
.
WithPrice
(
serverPrice
))
)
// put testdata in the mock store of the server
_
,
err
:=
mockStorer
.
Put
(
context
.
Background
(),
storage
.
ModePutUpload
,
chunk
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// create the server that will handle the request and will serve the response
server
:=
retrieval
.
New
(
swarm
.
MustParseHexAddress
(
"0034"
),
mockStorer
,
nil
,
nil
,
logger
,
serverMockAccounting
,
serverPricerMock
,
nil
)
recorder
:=
streamtest
.
New
(
streamtest
.
WithProtocols
(
server
.
Protocol
()),
streamtest
.
WithBaseAddr
(
clientAddr
),
)
// client mock storer does not store any data at this point
// but should be checked at at the end of the test for the
// presence of the chunk address key and value to ensure delivery
// was successful
clientMockStorer
:=
storemock
.
NewStorer
()
ps
:=
mockPeerSuggester
{
eachPeerRevFunc
:
func
(
f
topology
.
EachPeerFunc
)
error
{
_
,
_
,
_
=
f
(
serverAddr
,
0
)
return
nil
}}
client
:=
retrieval
.
New
(
clientAddr
,
clientMockStorer
,
recorder
,
ps
,
logger
,
clientMockAccounting
,
clientPricerMock
,
nil
)
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
testTimeout
)
defer
cancel
()
v
,
err
:=
client
.
RetrieveChunk
(
ctx
,
chunk
.
Address
())
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
v
.
Data
(),
chunk
.
Data
())
{
t
.
Fatalf
(
"request and response data not equal. got %s want %s"
,
v
,
chunk
.
Data
())
}
records
,
err
:=
recorder
.
Records
(
serverAddr
,
"retrieval"
,
"1.0.0"
,
"retrieval"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
l
:=
len
(
records
);
l
!=
1
{
t
.
Fatalf
(
"got %v records, want %v"
,
l
,
1
)
}
record
:=
records
[
0
]
messages
,
err
:=
protobuf
.
ReadMessages
(
bytes
.
NewReader
(
record
.
In
()),
func
()
protobuf
.
Message
{
return
new
(
pb
.
Request
)
},
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
var
reqs
[]
string
for
_
,
m
:=
range
messages
{
reqs
=
append
(
reqs
,
hex
.
EncodeToString
(
m
.
(
*
pb
.
Request
)
.
Addr
))
}
if
len
(
reqs
)
!=
1
{
t
.
Fatalf
(
"got too many requests. want 1 got %d"
,
len
(
reqs
))
}
messages
,
err
=
protobuf
.
ReadMessages
(
bytes
.
NewReader
(
record
.
Out
()),
func
()
protobuf
.
Message
{
return
new
(
pb
.
Delivery
)
},
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
var
gotDeliveries
[]
string
for
_
,
m
:=
range
messages
{
gotDeliveries
=
append
(
gotDeliveries
,
string
(
m
.
(
*
pb
.
Delivery
)
.
Data
))
}
if
len
(
gotDeliveries
)
!=
1
{
t
.
Fatalf
(
"got too many deliveries. want 1 got %d"
,
len
(
gotDeliveries
))
}
clientBalance
,
_
:=
clientMockAccounting
.
Balance
(
serverAddr
)
if
clientBalance
.
Cmp
(
big
.
NewInt
(
-
int64
(
serverPrice
)))
!=
0
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
serverPrice
,
clientBalance
)
}
serverBalance
,
_
:=
serverMockAccounting
.
Balance
(
clientAddr
)
if
serverBalance
.
Cmp
(
big
.
NewInt
(
int64
(
serverPrice
)))
!=
0
{
t
.
Fatalf
(
"unexpected balance on server. want %d got %d"
,
serverPrice
,
serverBalance
)
if
serverBalance
.
Int64
()
!=
int64
(
defaultPrice
)
{
t
.
Fatalf
(
"unexpected balance on server. want %d got %d"
,
defaultPrice
,
serverBalance
)
}
}
func
TestRetrieveChunk
(
t
*
testing
.
T
)
{
var
(
headlerFunc
=
func
(
h
p2p
.
Headers
,
a
swarm
.
Address
)
p2p
.
Headers
{
target
,
_
:=
headerutils
.
ParseTargetHeader
(
h
)
headers
,
_
:=
headerutils
.
MakePricingResponseHeaders
(
10
,
target
,
0
)
return
headers
}
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
pricer
=
pricermock
.
NewMockService
(
pricermock
.
WithPriceHeadlerFunc
(
headlerFunc
)
)
pricer
=
pricermock
.
NewMockService
(
defaultPrice
,
defaultPrice
)
)
// requesting a chunk from downstream peer is expected
...
...
@@ -362,14 +242,7 @@ func TestRetrievePreemptiveRetry(t *testing.T) {
chunk
:=
testingc
.
FixtureChunk
(
"0025"
)
someOtherChunk
:=
testingc
.
FixtureChunk
(
"0033"
)
headlerFunc
:=
func
(
h
p2p
.
Headers
,
a
swarm
.
Address
)
p2p
.
Headers
{
target
,
_
:=
headerutils
.
ParseTargetHeader
(
h
)
headers
,
_
:=
headerutils
.
MakePricingResponseHeaders
(
10
,
target
,
0
)
return
headers
}
price
:=
uint64
(
10
)
pricerMock
:=
pricermock
.
NewMockService
(
pricermock
.
WithPriceHeadlerFunc
(
headlerFunc
))
pricerMock
:=
pricermock
.
NewMockService
(
defaultPrice
,
defaultPrice
)
clientAddress
:=
swarm
.
MustParseHexAddress
(
"1010"
)
...
...
@@ -559,12 +432,12 @@ func TestRetrievePreemptiveRetry(t *testing.T) {
clientServer1Balance
,
_
:=
clientMockAccounting
.
Balance
(
serverAddress1
)
if
clientServer1Balance
.
Int64
()
!=
0
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
p
rice
,
clientServer1Balance
)
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
defaultP
rice
,
clientServer1Balance
)
}
clientServer2Balance
,
_
:=
clientMockAccounting
.
Balance
(
serverAddress2
)
if
clientServer2Balance
.
Int64
()
!=
-
int64
(
p
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
p
rice
,
clientServer2Balance
)
if
clientServer2Balance
.
Int64
()
!=
-
int64
(
defaultP
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
defaultP
rice
,
clientServer2Balance
)
}
// wait and check balance again
...
...
@@ -572,13 +445,13 @@ func TestRetrievePreemptiveRetry(t *testing.T) {
time
.
Sleep
(
2
*
time
.
Second
)
clientServer1Balance
,
_
=
clientMockAccounting
.
Balance
(
serverAddress1
)
if
clientServer1Balance
.
Int64
()
!=
-
int64
(
p
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
p
rice
,
clientServer1Balance
)
if
clientServer1Balance
.
Int64
()
!=
-
int64
(
defaultP
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
defaultP
rice
,
clientServer1Balance
)
}
clientServer2Balance
,
_
=
clientMockAccounting
.
Balance
(
serverAddress2
)
if
clientServer2Balance
.
Int64
()
!=
-
int64
(
p
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
p
rice
,
clientServer2Balance
)
if
clientServer2Balance
.
Int64
()
!=
-
int64
(
defaultP
rice
)
{
t
.
Fatalf
(
"unexpected balance on client. want %d got %d"
,
-
defaultP
rice
,
clientServer2Balance
)
}
})
...
...
pkg/topology/mock/mock.go
View file @
3217c6e1
...
...
@@ -18,6 +18,7 @@ type mock struct {
closestPeerErr
error
peersErr
error
addPeersErr
error
isWithinFunc
func
(
c
swarm
.
Address
)
bool
marshalJSONFunc
func
()
([]
byte
,
error
)
mtx
sync
.
Mutex
}
...
...
@@ -52,6 +53,12 @@ func WithMarshalJSONFunc(f func() ([]byte, error)) Option {
})
}
func
WithIsWithinFunc
(
f
func
(
swarm
.
Address
)
bool
)
Option
{
return
optionFunc
(
func
(
d
*
mock
)
{
d
.
isWithinFunc
=
f
})
}
func
NewTopologyDriver
(
opts
...
Option
)
topology
.
Driver
{
d
:=
new
(
mock
)
for
_
,
o
:=
range
opts
{
...
...
@@ -139,6 +146,9 @@ func (*mock) NeighborhoodDepth() uint8 {
}
func
(
m
*
mock
)
IsWithinDepth
(
addr
swarm
.
Address
)
bool
{
if
m
.
isWithinFunc
!=
nil
{
return
m
.
isWithinFunc
(
addr
)
}
return
false
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment