From d6c20e8b5d8f2cb96140b6ff2c0d23f0b189c033 Mon Sep 17 00:00:00 2001 From: Eric <5089238+emizzle@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:58:21 +1100 Subject: [PATCH] Clone and fix MarketplaceExample dist test The main issue was caused by an underflow in the partial payouts calculation. The underflow has been fixed. The rest is creation of the test and supporting changes for the test. --- codex/units.nim | 6 +++ tests/examples.nim | 7 ++- tests/integration/codexclient.nim | 9 ++-- tests/integration/codexconfig.nim | 12 ++++++ tests/integration/multinodes.nim | 6 --- tests/integration/testmarketplace.nim | 61 ++++++++++++++++++++++++++- vendor/codex-contracts-eth | 2 +- 7 files changed, 90 insertions(+), 13 deletions(-) diff --git a/codex/units.nim b/codex/units.nim index dcda8152..2691a1e5 100644 --- a/codex/units.nim +++ b/codex/units.nim @@ -14,6 +14,7 @@ import std/strutils import pkg/upraises import pkg/json_serialization import pkg/json_serialization/std/options +import pkg/stint type NBytes* = distinct Natural @@ -45,8 +46,10 @@ proc `'nb`*(n: string): NBytes = parseInt(n).NBytes const MiB = 1024.NBytes * 1024.NBytes # ByteSz, 1 mebibyte = 1,048,576 ByteSz + GiB = MiB * 1024.NBytes # ByteSz, 1 gigabyte = 1,073,741,824 ByteSz proc MiBs*(v: Natural): NBytes = v.NBytes * MiB +proc GiBs*(v: Natural): NBytes = v.NBytes * GiB func divUp*[T: NBytes](a, b : T): int = ## Division with result rounded up (rather than truncated as in 'div') @@ -65,6 +68,9 @@ proc readValue*( ) {.upraises: [SerializationError, IOError].} = value = NBytes reader.readValue(int) +func u256*(nbytes: NBytes): UInt256 = + Natural(nbytes).u256 + when isMainModule: import unittest2 diff --git a/tests/examples.nim b/tests/examples.nim index c8a8eace..f8ab3054 100644 --- a/tests/examples.nim +++ b/tests/examples.nim @@ -71,7 +71,10 @@ proc exampleProof*(): seq[byte] = proof = seq[byte].example return proof -proc exampleData*(): Future[seq[byte]] {.async.} = +proc exampleData*(size: NBytes): Future[seq[byte]] {.async.} = let rng = rng.Rng.instance() - let chunker = RandomChunker.new(rng, size = DefaultBlockSize * 2, chunkSize = DefaultBlockSize * 2) + let chunker = RandomChunker.new(rng, size = size, chunkSize = DefaultBlockSize * 2) return await chunker.getBytes() + +proc exampleData*(): Future[seq[byte]] {.async.} = + await exampleData(DefaultBlockSize * 2) diff --git a/tests/integration/codexclient.nim b/tests/integration/codexclient.nim index 68235237..0a402dd8 100644 --- a/tests/integration/codexclient.nim +++ b/tests/integration/codexclient.nim @@ -103,9 +103,12 @@ proc requestStorage*( proc getPurchase*(client: CodexClient, purchaseId: PurchaseId): ?!RestPurchase = let url = client.baseurl & "/storage/purchases/" & purchaseId.toHex - let body = client.http.getContent(url) - let json = ? parseJson(body).catch - RestPurchase.fromJson(json) + try: + let body = client.http.getContent(url) + let json = ? parseJson(body).catch + return RestPurchase.fromJson(json) + except CatchableError as e: + return failure e.msg proc getSalesAgent*(client: CodexClient, slotId: SlotId): ?!RestSalesAgent = let url = client.baseurl & "/sales/slots/" & slotId.toHex diff --git a/tests/integration/codexconfig.nim b/tests/integration/codexconfig.nim index b502d994..eda9c81a 100644 --- a/tests/integration/codexconfig.nim +++ b/tests/integration/codexconfig.nim @@ -1,5 +1,6 @@ import std/options import std/sequtils +import pkg/codex/units import ./clioption import ./nodeconfig @@ -47,3 +48,14 @@ proc withLogTopics*( var startConfig = config startConfig.logTopics = startConfig.logTopics.concat(@topics) return startConfig + +proc withStorageQuota*( + config: CodexConfig, + quota: NBytes +): CodexConfig = + + var startConfig = config + startConfig.cliOptions.add( + CliOption(key: "--storage-quota", value: $quota) + ) + return startConfig diff --git a/tests/integration/multinodes.nim b/tests/integration/multinodes.nim index 22e21c3e..0a4b54ec 100644 --- a/tests/integration/multinodes.nim +++ b/tests/integration/multinodes.nim @@ -34,12 +34,6 @@ type Validator, Hardhat -proc new*(_: type RunningNode, - role: Role, - node: NodeProcess): RunningNode = - RunningNode(role: role, - node: node) - proc nextFreePort(startPort: int): Future[int] {.async.} = let cmd = when defined(windows): "netstat -ano | findstr :" diff --git a/tests/integration/testmarketplace.nim b/tests/integration/testmarketplace.nim index 924b2d03..0d0655b0 100644 --- a/tests/integration/testmarketplace.nim +++ b/tests/integration/testmarketplace.nim @@ -1,4 +1,5 @@ import pkg/stew/byteutils +import pkg/codex/units import ./marketplacesuite import ../examples @@ -80,4 +81,62 @@ marketplacesuite "Marketplace payouts": (startBalanceClient - endBalanceClient) == (endBalanceProvider - startBalanceProvider) ) - await subscription.unsubscribe() \ No newline at end of file + await subscription.unsubscribe() + +marketplacesuite "Marketplace example (dist test clone)": + + test "Marketplace example", + NodeConfigs( + # Uncomment to start Hardhat automatically, typically so logs can be inspected locally + # hardhat: HardhatConfig().withLogFile() + + clients: + CodexConfig() + .nodes(1) + # .debug() # uncomment to enable console log output.debug() + .withLogFile() # uncomment to output log file to tests/integration/logs/ //_.log + .withLogTopics("node", "erasure", "restapi"), + + providers: + CodexConfig() + .nodes(1) + # .debug() # uncomment to enable console log output + .simulateProofFailuresFor(providerIdx=0, failEveryNProofs=3) + .withStorageQuota(11.GiBs) + .withLogFile() # uncomment to output log file to tests/integration/logs/ //_.log + .withLogTopics("marketplace", "sales", "reservations", "node", "proving", "clock", "restapi"), + ): + let reward = 400.u256 + let duration = 100.periods + let collateral = 200.u256 + let expiry = 4.periods + let data = byteutils.toHex(await exampleData(10.MiBs)) + let client = clients()[0] + let provider = providers()[0] + let clientApi = client.client + let providerApi = provider.client + let startBalanceProvider = await token.balanceOf(provider.ethAccount) + let startBalanceClient = await token.balanceOf(client.ethAccount) + + # provider makes storage available + discard providerApi.postAvailability( + size=10.GiBs.u256, + duration=180.u256, + minPrice=1.u256, + maxCollateral=20.u256) + + let cid = clientApi.upload(data).get + + # client requests storage but requires two nodes to host the content + trace "requesting storage" + let id = await clientApi.requestStorage( + cid, + proofProbability=5.uint64, + duration=60.uint64, + reward=2.u256, + collateral=10.u256, + expiry=300.uint64 + ) + + trace "checking purchase state" + check eventually(clientApi.purchaseStateIs(id, "started")) diff --git a/vendor/codex-contracts-eth b/vendor/codex-contracts-eth index e6298f60..840447ed 160000 --- a/vendor/codex-contracts-eth +++ b/vendor/codex-contracts-eth @@ -1 +1 @@ -Subproject commit e6298f60392b80c43a080a50f943210a08743bd4 +Subproject commit 840447ed803ea5cd5e808fe37bc335912cb32aaf