Add proc to engine that pays peers for bytes
This commit is contained in:
parent
ad48f55aaa
commit
9512bbc50b
|
@ -0,0 +1,40 @@
|
|||
import std/math
|
||||
import pkg/nitro
|
||||
import pkg/questionable/results
|
||||
import ../peercontext
|
||||
|
||||
export nitro
|
||||
export results
|
||||
export peercontext
|
||||
|
||||
push: {.upraises: [].}
|
||||
|
||||
const ChainId = 0.u256 # invalid chain id for now
|
||||
const AmountPerChannel = (10^18).u256 # 1 asset, ERC20 default is 18 decimals
|
||||
|
||||
func openLedgerChannel*(wallet: var Wallet,
|
||||
hub: EthAddress,
|
||||
asset: EthAddress): ?!ChannelId =
|
||||
wallet.openLedgerChannel(hub, ChainId, asset, AmountPerChannel)
|
||||
|
||||
func getOrOpenChannel(wallet: var Wallet, peer: BitswapPeerCtx): ?!ChannelId =
|
||||
if channel =? peer.paymentChannel:
|
||||
channel.success
|
||||
elif pricing =? peer.pricing:
|
||||
let channel = ?wallet.openLedgerChannel(pricing.address, pricing.asset)
|
||||
peer.paymentChannel = channel.some
|
||||
channel.success
|
||||
else:
|
||||
ChannelId.failure "no pricing set for peer"
|
||||
|
||||
func pay*(wallet: var Wallet,
|
||||
peer: BitswapPeerCtx,
|
||||
amountOfBytes: int): ?!SignedState =
|
||||
if pricing =? peer.pricing:
|
||||
let amount = amountOfBytes.u256 * pricing.price
|
||||
let asset = pricing.asset
|
||||
let receiver = pricing.address
|
||||
let channel = ?wallet.getOrOpenChannel(peer)
|
||||
wallet.pay(channel, asset, receiver, amount)
|
||||
else:
|
||||
SignedState.failure "no pricing set for peer"
|
|
@ -1,20 +1,25 @@
|
|||
import std/sequtils
|
||||
import pkg/libp2p
|
||||
import pkg/chronos
|
||||
import pkg/nitro
|
||||
import pkg/questionable
|
||||
import ./protobuf/bitswap
|
||||
import ./protobuf/payments
|
||||
|
||||
export payments
|
||||
export nitro
|
||||
|
||||
type
|
||||
BitswapPeerCtx* = ref object of RootObj
|
||||
id*: PeerID
|
||||
peerHave*: seq[Cid] # remote peers have lists
|
||||
peerWants*: seq[Entry] # remote peers want lists
|
||||
bytesSent*: int # bytes sent to remote
|
||||
bytesRecv*: int # bytes received from remote
|
||||
exchanged*: int # times peer has exchanged with us
|
||||
lastExchange*: Moment # last time peer has exchanged with us
|
||||
pricing*: ?Pricing # optional bandwidth price for this peer
|
||||
peerHave*: seq[Cid] # remote peers have lists
|
||||
peerWants*: seq[Entry] # remote peers want lists
|
||||
bytesSent*: int # bytes sent to remote
|
||||
bytesRecv*: int # bytes received from remote
|
||||
exchanged*: int # times peer has exchanged with us
|
||||
lastExchange*: Moment # last time peer has exchanged with us
|
||||
pricing*: ?Pricing # optional bandwidth price for this peer
|
||||
paymentChannel*: ?ChannelId # payment channel id
|
||||
|
||||
proc contains*(a: openArray[BitswapPeerCtx], b: PeerID): bool =
|
||||
## Convenience method to check for peer prepense
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import pkg/protobuf_serialization
|
||||
import pkg/stew/byteutils
|
||||
import pkg/stint
|
||||
import pkg/nitro
|
||||
import pkg/questionable
|
||||
import pkg/upraises
|
||||
|
@ -8,6 +9,7 @@ import ./bitswap
|
|||
export PricingMessage
|
||||
export StateChannelUpdate
|
||||
|
||||
export stint
|
||||
export nitro
|
||||
|
||||
push: {.upraises: [].}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import std/unittest
|
||||
import pkg/dagger/bitswap/engine/payments
|
||||
import ../../examples
|
||||
|
||||
suite "engine payments":
|
||||
|
||||
let amountOfBytes = 42
|
||||
|
||||
var wallet: Wallet
|
||||
var peer: BitswapPeerCtx
|
||||
|
||||
setup:
|
||||
wallet = Wallet.example
|
||||
peer = BitswapPeerCtx.example
|
||||
peer.pricing = Pricing.example.some
|
||||
|
||||
test "pays for received bytes":
|
||||
let payment = wallet.pay(peer, amountOfBytes).get
|
||||
let pricing = peer.pricing.get
|
||||
let balances = payment.state.outcome.balances(pricing.asset)
|
||||
let destination = pricing.address.toDestination
|
||||
check balances[destination].get == amountOfBytes.u256 * pricing.price
|
||||
|
||||
test "no payment when no price is set":
|
||||
peer.pricing = Pricing.none
|
||||
check wallet.pay(peer, amountOfBytes).isErr
|
||||
|
||||
test "uses same channel for consecutive payments":
|
||||
let payment1, payment2 = wallet.pay(peer, amountOfBytes)
|
||||
let channel1 = payment1.?state.?channel.?getChannelId
|
||||
let channel2 = payment2.?state.?channel.?getChannelId
|
||||
check channel1 == channel2
|
|
@ -1,6 +1,11 @@
|
|||
import std/random
|
||||
import std/sequtils
|
||||
import pkg/libp2p
|
||||
import pkg/nitro
|
||||
import pkg/dagger/p2p/rng
|
||||
import pkg/dagger/bitswap/protobuf/payments
|
||||
import pkg/dagger/bitswap/peercontext
|
||||
import pkg/dagger/blocktype
|
||||
|
||||
proc example*(_: type EthAddress): EthAddress =
|
||||
EthPrivateKey.random().toPublicKey.toAddress
|
||||
|
@ -30,5 +35,17 @@ proc example*(_: type Pricing): Pricing =
|
|||
Pricing(
|
||||
address: EthAddress.example,
|
||||
asset: EthAddress.example,
|
||||
price: UInt256.example()
|
||||
price: uint32.example.u256
|
||||
)
|
||||
|
||||
proc example*(_: type Block): Block =
|
||||
let length = rand(4096)
|
||||
let bytes = newSeqWith(length, rand(uint8))
|
||||
Block.new(bytes)
|
||||
|
||||
proc example*(_: type PeerId): PeerID =
|
||||
let key = PrivateKey.random(Rng.instance[]).get
|
||||
PeerId.init(key.getKey().get).get
|
||||
|
||||
proc example*(_: type BitswapPeerCtx): BitswapPeerCtx =
|
||||
BitswapPeerCtx(id: PeerID.example)
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import ./dagger/bitswap/testbitswap
|
||||
import ./dagger/bitswap/testengine
|
||||
import ./dagger/bitswap/testnetwork
|
||||
import ./dagger/bitswap/protobuf/testpayments
|
||||
import ./dagger/bitswap/protobuf/testpayments as testprotobufpayments
|
||||
import ./dagger/bitswap/engine/testpayments as testenginepayments
|
||||
import ./dagger/testasyncheapqueue
|
||||
import ./dagger/testblockstore
|
||||
import ./dagger/testchunking
|
||||
|
|
Loading…
Reference in New Issue