diff --git a/dagger/bitswap/protobuf/message.proto b/dagger/bitswap/protobuf/message.proto index d02810eb..af4e2562 100644 --- a/dagger/bitswap/protobuf/message.proto +++ b/dagger/bitswap/protobuf/message.proto @@ -35,6 +35,7 @@ message Message { message BlockPresence { bytes cid = 1; BlockPresenceType type = 2; + bytes price = 3; // Amount of assets to pay per byte (UInt256) } message PricingMessage { diff --git a/dagger/bitswap/protobuf/presence.nim b/dagger/bitswap/protobuf/presence.nim new file mode 100644 index 00000000..a51a4a1f --- /dev/null +++ b/dagger/bitswap/protobuf/presence.nim @@ -0,0 +1,46 @@ +import libp2p +import pkg/stint +import pkg/questionable +import pkg/questionable/results +import pkg/upraises +import ./bitswap + +export questionable +export stint +export BlockPresenceType + +upraises.push: {.upraises: [].} + +type + PresenceMessage* = bitswap.BlockPresence + Presence* = object + cid*: Cid + have*: bool + price*: UInt256 + +func init*(_: type PresenceMessage, presence: Presence): PresenceMessage = + PresenceMessage( + cid: presence.cid.data.buffer, + `type`: if presence.have: presenceHave else: presenceDontHave, + price: @(presence.price.toBytesBE) + ) + +func parse(_: type UInt256, bytes: seq[byte]): ?UInt256 = + if bytes.len > 32: + return UInt256.none + UInt256.fromBytesBE(bytes).some + +func init*(_: type Presence, message: PresenceMessage): ?Presence = + mixin parsedCid, parsedPrice + + without parsedCid =? Cid.init(message.cid): + return none Presence + + without parsedPrice =? UInt256.parse(message.price): + return none Presence + + some Presence( + cid: parsedCid, + have: message.`type` == presenceHave, + price: parsedPrice + ) diff --git a/tests/dagger/bitswap/protobuf/testpresence.nim b/tests/dagger/bitswap/protobuf/testpresence.nim new file mode 100644 index 00000000..c5dbc5bb --- /dev/null +++ b/tests/dagger/bitswap/protobuf/testpresence.nim @@ -0,0 +1,49 @@ +import std/sequtils +import pkg/asynctest +import pkg/chronos +import pkg/libp2p +import ../../../../dagger/bitswap/protobuf/presence +import ../../examples + +suite "block presence protobuf messages": + + let cid = Cid.example + let price = UInt256.example + let presence = Presence(cid: cid, have: true, price: price) + let message = PresenceMessage.init(presence) + + test "encodes CID": + check message.cid == cid.data.buffer + + test "encodes have/donthave": + var presence = presence + presence.have = true + check PresenceMessage.init(presence).`type` == presenceHave + presence.have = false + check PresenceMessage.init(presence).`type` == presenceDontHave + + test "encodes price": + check message.price == @(price.toBytesBE) + + test "decodes CID": + check Presence.init(message).?cid == cid.some + + test "fails to decode when CID is invalid": + var incorrect = message + incorrect.cid.del(0) + check Presence.init(incorrect).isNone + + test "decodes have/donthave": + var message = message + message.`type` = presenceHave + check Presence.init(message).?have == true.some + message.`type` = presenceDontHave + check Presence.init(message).?have == false.some + + test "decodes price": + check Presence.init(message).?price == price.some + + test "fails to decode when price is invalid": + var incorrect = message + incorrect.price.add(0) + check Presence.init(incorrect).isNone diff --git a/tests/dagger/examples.nim b/tests/dagger/examples.nim index 3f1b475f..1cdbc428 100644 --- a/tests/dagger/examples.nim +++ b/tests/dagger/examples.nim @@ -51,3 +51,6 @@ proc example*(_: type PeerId): PeerID = proc example*(_: type BitswapPeerCtx): BitswapPeerCtx = BitswapPeerCtx(id: PeerID.example) + +proc example*(_: type Cid): Cid = + Block.example.cid diff --git a/tests/testAll.nim b/tests/testAll.nim index 2b03c4a7..975c3d61 100644 --- a/tests/testAll.nim +++ b/tests/testAll.nim @@ -2,6 +2,7 @@ import ./dagger/bitswap/testbitswap import ./dagger/bitswap/testengine import ./dagger/bitswap/testnetwork import ./dagger/bitswap/protobuf/testpayments as testprotobufpayments +import ./dagger/bitswap/protobuf/testpresence import ./dagger/bitswap/engine/testpayments as testenginepayments import ./dagger/testasyncheapqueue import ./dagger/testblockstore