Introduce Purchasing and Market
This commit is contained in:
parent
a3fdd35f73
commit
5f10549f19
|
@ -0,0 +1,11 @@
|
||||||
|
import pkg/chronos
|
||||||
|
import ./contracts/requests
|
||||||
|
|
||||||
|
export chronos
|
||||||
|
export requests
|
||||||
|
|
||||||
|
type
|
||||||
|
Market* = ref object of RootObj
|
||||||
|
|
||||||
|
method requestStorage*(market: Market, request: StorageRequest) {.base, async.} =
|
||||||
|
raiseAssert("not implemented")
|
|
@ -0,0 +1,57 @@
|
||||||
|
import std/times
|
||||||
|
import pkg/stint
|
||||||
|
import pkg/chronos
|
||||||
|
import pkg/questionable
|
||||||
|
import pkg/nimcrypto
|
||||||
|
import ./market
|
||||||
|
|
||||||
|
export questionable
|
||||||
|
|
||||||
|
type
|
||||||
|
Purchasing* = ref object
|
||||||
|
market: Market
|
||||||
|
proofProbability*: UInt256
|
||||||
|
requestExpiryInterval*: UInt256
|
||||||
|
PurchaseRequest* = object
|
||||||
|
duration*: UInt256
|
||||||
|
size*: UInt256
|
||||||
|
contentHash*: array[32, byte]
|
||||||
|
maxPrice*: UInt256
|
||||||
|
proofProbability*: ?UInt256
|
||||||
|
expiry*: ?UInt256
|
||||||
|
Purchase* = ref object
|
||||||
|
|
||||||
|
const DefaultProofProbability = 100.u256
|
||||||
|
const DefaultRequestExpiryInterval = (10 * 60).u256
|
||||||
|
|
||||||
|
proc new*(_: type Purchasing, market: Market): Purchasing =
|
||||||
|
Purchasing(
|
||||||
|
market: market,
|
||||||
|
proofProbability: DefaultProofProbability,
|
||||||
|
requestExpiryInterval: DefaultRequestExpiryInterval
|
||||||
|
)
|
||||||
|
|
||||||
|
proc getProofProbability(purchasing: Purchasing, request: PurchaseRequest): UInt256 =
|
||||||
|
request.proofProbability |? purchasing.proofProbability
|
||||||
|
|
||||||
|
proc getExpiry(purchasing: Purchasing, request: PurchaseRequest): UInt256 =
|
||||||
|
request.expiry |? (getTime().toUnix().u256 + purchasing.requestExpiryInterval)
|
||||||
|
|
||||||
|
proc getNonce(): array[32, byte] =
|
||||||
|
doAssert randomBytes(result) == 32
|
||||||
|
|
||||||
|
proc purchase*(purchasing: Purchasing, request: PurchaseRequest): Purchase =
|
||||||
|
let request: StorageRequest = (
|
||||||
|
client: Address.default, # TODO
|
||||||
|
duration: request.duration,
|
||||||
|
size: request.size,
|
||||||
|
contentHash: request.contentHash,
|
||||||
|
proofProbability: purchasing.getProofProbability(request),
|
||||||
|
maxPrice: request.maxPrice,
|
||||||
|
expiry: purchasing.getExpiry(request),
|
||||||
|
nonce: getNonce()
|
||||||
|
)
|
||||||
|
asyncSpawn purchasing.market.requestStorage(request)
|
||||||
|
|
||||||
|
proc wait*(purchase: Purchase) {.async.} =
|
||||||
|
discard
|
|
@ -2,9 +2,11 @@ import std/random
|
||||||
import std/sequtils
|
import std/sequtils
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
import pkg/nitro
|
import pkg/nitro
|
||||||
|
import pkg/stint
|
||||||
import pkg/dagger/rng
|
import pkg/dagger/rng
|
||||||
import pkg/dagger/stores
|
import pkg/dagger/stores
|
||||||
import pkg/dagger/blocktype
|
import pkg/dagger/blocktype
|
||||||
|
import pkg/dagger/purchasing
|
||||||
|
|
||||||
proc example*(_: type EthAddress): EthAddress =
|
proc example*(_: type EthAddress): EthAddress =
|
||||||
EthPrivateKey.random().toPublicKey.toAddress
|
EthPrivateKey.random().toPublicKey.toAddress
|
||||||
|
@ -19,6 +21,13 @@ proc example*(_: type UInt48): UInt48 =
|
||||||
# workaround for https://github.com/nim-lang/Nim/issues/17670
|
# workaround for https://github.com/nim-lang/Nim/issues/17670
|
||||||
uint64.rand mod (UInt48.high + 1)
|
uint64.rand mod (UInt48.high + 1)
|
||||||
|
|
||||||
|
proc example*[T: SomeInteger](_: type T): T =
|
||||||
|
rand(T)
|
||||||
|
|
||||||
|
proc example*[T,N](_: type array[N, T]): array[N, T] =
|
||||||
|
for item in result.mitems:
|
||||||
|
item = T.example
|
||||||
|
|
||||||
proc example*(_: type Wallet): Wallet =
|
proc example*(_: type Wallet): Wallet =
|
||||||
Wallet.init(EthPrivateKey.random())
|
Wallet.init(EthPrivateKey.random())
|
||||||
|
|
||||||
|
@ -53,3 +62,10 @@ proc example*(_: type BlockExcPeerCtx): BlockExcPeerCtx =
|
||||||
|
|
||||||
proc example*(_: type Cid): Cid =
|
proc example*(_: type Cid): Cid =
|
||||||
Block.example.cid
|
Block.example.cid
|
||||||
|
|
||||||
|
proc example*(_: type PurchaseRequest): PurchaseRequest =
|
||||||
|
PurchaseRequest(
|
||||||
|
duration: uint16.example.u256,
|
||||||
|
size: uint32.example.u256,
|
||||||
|
contentHash: array[32, byte].example
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import pkg/dagger/market
|
||||||
|
|
||||||
|
type
|
||||||
|
MockMarket* = ref object of Market
|
||||||
|
requests*: seq[StorageRequest]
|
||||||
|
|
||||||
|
method requestStorage*(market: MockMarket, request: StorageRequest) {.async.} =
|
||||||
|
market.requests.add(request)
|
|
@ -0,0 +1,59 @@
|
||||||
|
import std/times
|
||||||
|
import pkg/asynctest
|
||||||
|
import pkg/chronos
|
||||||
|
import pkg/stint
|
||||||
|
import pkg/dagger/purchasing
|
||||||
|
import ./helpers/mockmarket
|
||||||
|
import ./examples
|
||||||
|
|
||||||
|
suite "Purchasing":
|
||||||
|
|
||||||
|
var purchasing: Purchasing
|
||||||
|
var market: MockMarket
|
||||||
|
var purchaseRequest: PurchaseRequest
|
||||||
|
|
||||||
|
setup:
|
||||||
|
market = MockMarket.new()
|
||||||
|
purchasing = Purchasing.new(market)
|
||||||
|
purchaseRequest = PurchaseRequest.example
|
||||||
|
|
||||||
|
test "submits a storage request when asked":
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
let storageRequest = market.requests[0]
|
||||||
|
check storageRequest.duration == purchaseRequest.duration
|
||||||
|
check storageRequest.size == purchaseRequest.size
|
||||||
|
check storageRequest.contentHash == purchaseRequest.contentHash
|
||||||
|
check storageRequest.maxPrice == purchaseRequest.maxPrice
|
||||||
|
|
||||||
|
test "has a default value for proof probability":
|
||||||
|
check purchasing.proofProbability != 0.u256
|
||||||
|
|
||||||
|
test "can change default value for proof probability":
|
||||||
|
purchasing.proofProbability = 42.u256
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
check market.requests[0].proofProbability == 42.u256
|
||||||
|
|
||||||
|
test "can override proof probability per request":
|
||||||
|
purchaseRequest.proofProbability = some 42.u256
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
check market.requests[0].proofProbability == 42.u256
|
||||||
|
|
||||||
|
test "has a default value for request expiration interval":
|
||||||
|
check purchasing.requestExpiryInterval != 0.u256
|
||||||
|
|
||||||
|
test "can change default value for request expiration interval":
|
||||||
|
purchasing.requestExpiryInterval = 42.u256
|
||||||
|
let start = getTime().toUnix()
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
check market.requests[0].expiry == (start + 42).u256
|
||||||
|
|
||||||
|
test "can override expiry time per request":
|
||||||
|
let expiry = (getTime().toUnix() + 42).u256
|
||||||
|
purchaseRequest.expiry = some expiry
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
check market.requests[0].expiry == expiry
|
||||||
|
|
||||||
|
test "includes a random nonce in every storage request":
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
await purchasing.purchase(purchaseRequest).wait()
|
||||||
|
check market.requests[0].nonce != market.requests[1].nonce
|
|
@ -5,5 +5,6 @@ import ./dagger/testchunking
|
||||||
import ./dagger/testmanifest
|
import ./dagger/testmanifest
|
||||||
import ./dagger/testnode
|
import ./dagger/testnode
|
||||||
import ./dagger/teststorestream
|
import ./dagger/teststorestream
|
||||||
|
import ./dagger/testpurchasing
|
||||||
|
|
||||||
{.warning[UnusedImport]: off.}
|
{.warning[UnusedImport]: off.}
|
||||||
|
|
Loading…
Reference in New Issue