diff --git a/.github/workflows/ci-reusable.yml b/.github/workflows/ci-reusable.yml index 605edeed..55846d89 100644 --- a/.github/workflows/ci-reusable.yml +++ b/.github/workflows/ci-reusable.yml @@ -26,7 +26,7 @@ jobs: name: ${{ matrix.os }}-${{ matrix.tests }}-${{ matrix.cpu }}-${{ matrix.nim_version }} runs-on: ${{ matrix.builder }} - timeout-minutes: 100 + timeout-minutes: 120 steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/codex/contracts/market.nim b/codex/contracts/market.nim index b8d1da68..fdddcb22 100644 --- a/codex/contracts/market.nim +++ b/codex/contracts/market.nim @@ -53,7 +53,7 @@ proc approveFunds(market: OnChainMarket, amount: UInt256) {.async.} = convertEthersError: let tokenAddress = await market.contract.token() let token = Erc20Token.new(tokenAddress, market.signer) - discard await token.increaseAllowance(market.contract.address(), amount).confirm(0) + discard await token.increaseAllowance(market.contract.address(), amount).confirm(1) method getZkeyHash*(market: OnChainMarket): Future[?string] {.async.} = let config = await market.contract.configuration() @@ -99,7 +99,7 @@ method requestStorage(market: OnChainMarket, request: StorageRequest){.async.} = convertEthersError: debug "Requesting storage" await market.approveFunds(request.price()) - discard await market.contract.requestStorage(request).confirm(0) + discard await market.contract.requestStorage(request).confirm(1) method getRequest(market: OnChainMarket, id: RequestId): Future[?StorageRequest] {.async.} = @@ -171,7 +171,7 @@ method fillSlot(market: OnChainMarket, await market.approveFunds(collateral) trace "calling fillSlot on contract" - discard await market.contract.fillSlot(requestId, slotIndex, proof).confirm(0) + discard await market.contract.fillSlot(requestId, slotIndex, proof).confirm(1) trace "fillSlot transaction completed" method freeSlot*(market: OnChainMarket, slotId: SlotId) {.async.} = @@ -191,13 +191,13 @@ method freeSlot*(market: OnChainMarket, slotId: SlotId) {.async.} = # recipient (the contract will use msg.sender for both) freeSlot = market.contract.freeSlot(slotId) - discard await freeSlot.confirm(0) + discard await freeSlot.confirm(1) method withdrawFunds(market: OnChainMarket, requestId: RequestId) {.async.} = convertEthersError: - discard await market.contract.withdrawFunds(requestId).confirm(0) + discard await market.contract.withdrawFunds(requestId).confirm(1) method isProofRequired*(market: OnChainMarket, id: SlotId): Future[bool] {.async.} = @@ -230,13 +230,13 @@ method submitProof*(market: OnChainMarket, id: SlotId, proof: Groth16Proof) {.async.} = convertEthersError: - discard await market.contract.submitProof(id, proof).confirm(0) + discard await market.contract.submitProof(id, proof).confirm(1) method markProofAsMissing*(market: OnChainMarket, id: SlotId, period: Period) {.async.} = convertEthersError: - discard await market.contract.markProofAsMissing(id, period).confirm(0) + discard await market.contract.markProofAsMissing(id, period).confirm(1) method canProofBeMarkedAsMissing*( market: OnChainMarket, @@ -264,7 +264,7 @@ method reserveSlot*( slotIndex, # reserveSlot runs out of gas for unknown reason, but 100k gas covers it TransactionOverrides(gasLimit: some 100000.u256) - ).confirm(0) + ).confirm(1) method canReserveSlot*( market: OnChainMarket, diff --git a/tests/codex/testvalidation.nim b/tests/codex/testvalidation.nim index e67172f7..7988269b 100644 --- a/tests/codex/testvalidation.nim +++ b/tests/codex/testvalidation.nim @@ -67,7 +67,7 @@ asyncchecksuite "validation": check validationConfig.error.msg == "The value of the group index " & "must be less than validation groups! " & fmt"(got: {groupIndex = }, groups = {!groups})" - + test "initializing ValidationConfig fails when maxSlots is negative": let maxSlots = -1 let validationConfig = ValidationConfig.init( @@ -75,7 +75,7 @@ asyncchecksuite "validation": check validationConfig.isFailure == true check validationConfig.error.msg == "The value of maxSlots must " & fmt"be greater than or equal to 0! (got: {maxSlots})" - + test "initializing ValidationConfig fails when maxSlots is negative " & "(validationGroups set)": let maxSlots = -1 @@ -97,7 +97,7 @@ asyncchecksuite "validation": test "when a slot is filled on chain, it is added to the list": await market.fillSlot(slot.request.id, slot.slotIndex, proof, collateral) check validation.slots == @[slot.id] - + test "slot should be observed if maxSlots is set to 0": let validationConfig = initValidationConfig( maxSlots = 0, ValidationGroups.none) @@ -128,14 +128,14 @@ asyncchecksuite "validation": await market.fillSlot(slot.request.id, slot.slotIndex, proof, collateral) market.setCanProofBeMarkedAsMissing(slot.id, true) advanceToNextPeriod() - await sleepAsync(1.millis) + await sleepAsync(100.millis) # allow validation loop to run check market.markedAsMissingProofs.contains(slot.id) test "when a proof can not be marked as missing, it will not be marked": await market.fillSlot(slot.request.id, slot.slotIndex, proof, collateral) market.setCanProofBeMarkedAsMissing(slot.id, false) advanceToNextPeriod() - await sleepAsync(1.millis) + await sleepAsync(100.millis) # allow validation loop to run check market.markedAsMissingProofs.len == 0 test "it does not monitor more than the maximum number of slots": diff --git a/tests/contracts/testClock.nim b/tests/contracts/testClock.nim index 40f7aed0..abc47496 100644 --- a/tests/contracts/testClock.nim +++ b/tests/contracts/testClock.nim @@ -30,7 +30,7 @@ ethersuite "On-Chain Clock": let waiting = clock.waitUntil(future) discard await ethProvider.send("evm_setNextBlockTimestamp", @[%future]) discard await ethProvider.send("evm_mine") - check await waiting.withTimeout(chronos.milliseconds(100)) + check await waiting.withTimeout(chronos.milliseconds(500)) test "can wait until a certain time is reached by the wall-clock": let future = clock.now() + 1 # seconds diff --git a/tests/contracts/testContracts.nim b/tests/contracts/testContracts.nim index bbbf41aa..3b95c5fc 100644 --- a/tests/contracts/testContracts.nim +++ b/tests/contracts/testContracts.nim @@ -45,13 +45,13 @@ ethersuite "Marketplace contracts": request.client = await client.getAddress() switchAccount(client) - discard await token.approve(marketplace.address, request.price) - discard await marketplace.requestStorage(request) + discard await token.approve(marketplace.address, request.price).confirm(1) + discard await marketplace.requestStorage(request).confirm(1) switchAccount(host) - discard await token.approve(marketplace.address, request.ask.collateral) - discard await marketplace.reserveSlot(request.id, 0.u256) - filledAt = await ethProvider.currentTime() - discard await marketplace.fillSlot(request.id, 0.u256, proof) + discard await token.approve(marketplace.address, request.ask.collateral).confirm(1) + discard await marketplace.reserveSlot(request.id, 0.u256).confirm(1) + let receipt = await marketplace.fillSlot(request.id, 0.u256, proof).confirm(1) + filledAt = await ethProvider.blockTime(BlockTag.init(!receipt.blockNumber)) slotId = request.slotId(0.u256) proc waitUntilProofRequired(slotId: SlotId) {.async.} = @@ -65,14 +65,14 @@ ethersuite "Marketplace contracts": proc startContract() {.async.} = for slotIndex in 1.. 0 and newSize < size let reservations = client2.getAvailabilityReservations(availability.id).get - check reservations.len == 5 + check reservations.len == 3 check reservations[0].requestId == purchase.requestId test "node slots gets paid out and rest of tokens are returned to client": @@ -51,8 +51,8 @@ twonodessuite "Marketplace", debug1 = false, debug2 = false: let tokenAddress = await marketplace.token() let token = Erc20Token.new(tokenAddress, ethProvider.getSigner()) let reward = 400.u256 - let duration = 10*60.u256 - let nodes = 5'u + let duration = 20*60.u256 + let nodes = 3'u # client 2 makes storage available let startBalanceHost = await token.balanceOf(account2) @@ -65,12 +65,12 @@ twonodessuite "Marketplace", debug1 = false, debug2 = false: duration=duration, reward=reward, proofProbability=3.u256, - expiry=5*60, + expiry=10*60, collateral=200.u256, nodes = nodes, - tolerance = 2).get + tolerance = 1).get - check eventually(client1.purchaseStateIs(id, "started"), timeout=5*60*1000) + check eventually(client1.purchaseStateIs(id, "started"), timeout=10*60*1000) let purchase = client1.getPurchase(id).get check purchase.error == none string @@ -85,7 +85,10 @@ twonodessuite "Marketplace", debug1 = false, debug2 = false: check eventually (await token.balanceOf(account2)) - startBalanceHost >= (duration-5*60)*reward*nodes.u256 # Checking that client node receives some funds back that were not used for the host nodes - check eventually (await token.balanceOf(account1)) - clientBalanceBeforeFinished > 0 + check eventually( + (await token.balanceOf(account1)) - clientBalanceBeforeFinished > 0, + timeout = 10*1000 # give client a bit of time to withdraw its funds + ) marketplacesuite "Marketplace payouts": @@ -109,9 +112,9 @@ marketplacesuite "Marketplace payouts": .some, ): let reward = 400.u256 - let duration = 10.periods + let duration = 20.periods let collateral = 200.u256 - let expiry = 5.periods + let expiry = 10.periods let data = await RandomChunker.example(blocks=8) let client = clients()[0] let provider = providers()[0] @@ -150,22 +153,24 @@ marketplacesuite "Marketplace payouts": # wait until one slot is filled check eventually(slotIdxFilled.isSome, timeout=expiry.int * 1000) + let slotId = slotId(!clientApi.requestId(id), !slotIdxFilled) # wait until sale is cancelled - without requestId =? clientApi.requestId(id): - fail() - let slotId = slotId(requestId, !slotIdxFilled) - check eventually(providerApi.saleStateIs(slotId, "SaleCancelled"), timeout=expiry.int * 1000) + await ethProvider.advanceTime(expiry.u256) + check eventually providerApi.saleStateIs(slotId, "SaleCancelled") check eventually ( let endBalanceProvider = (await token.balanceOf(provider.ethAccount)); endBalanceProvider > startBalanceProvider and endBalanceProvider < startBalanceProvider + expiry.u256*reward ) - check eventually ( - let endBalanceClient = (await token.balanceOf(client.ethAccount)); - let endBalanceProvider = (await token.balanceOf(provider.ethAccount)); - (startBalanceClient - endBalanceClient) == (endBalanceProvider - startBalanceProvider) + check eventually( + ( + let endBalanceClient = (await token.balanceOf(client.ethAccount)); + let endBalanceProvider = (await token.balanceOf(provider.ethAccount)); + (startBalanceClient - endBalanceClient) == (endBalanceProvider - startBalanceProvider) + ), + timeout = 10*1000 # give client a bit of time to withdraw its funds ) await subscription.unsubscribe() diff --git a/tests/integration/testproofs.nim b/tests/integration/testproofs.nim index 057d7f46..0d8b9bd3 100644 --- a/tests/integration/testproofs.nim +++ b/tests/integration/testproofs.nim @@ -36,7 +36,7 @@ marketplacesuite "Hosts submit regular proofs": .some, ): let client0 = clients()[0].client - let expiry = 5.periods + let expiry = 10.periods let duration = expiry + 5.periods let data = await RandomChunker.example(blocks=8) @@ -99,7 +99,7 @@ marketplacesuite "Simulate invalid proofs": .some ): let client0 = clients()[0].client - let expiry = 5.periods + let expiry = 10.periods let duration = expiry + 10.periods let data = await RandomChunker.example(blocks=8) @@ -157,9 +157,8 @@ marketplacesuite "Simulate invalid proofs": .some ): let client0 = clients()[0].client - let expiry = 5.periods - # In 2 periods you cannot have enough invalid proofs submitted: - let duration = expiry + 2.periods + let expiry = 10.periods + let duration = expiry + 10.periods let data = await RandomChunker.example(blocks=8) createAvailabilities(data.len * 2, duration) # TODO: better value for data.len @@ -176,20 +175,27 @@ marketplacesuite "Simulate invalid proofs": ) let requestId = client0.requestId(purchaseId).get - check eventually(client0.purchaseStateIs(purchaseId, "started"), timeout = expiry.int * 1000) + var slotWasFilled = false + proc onSlotFilled(event: SlotFilled) = + if event.requestId == requestId: + slotWasFilled = true + let filledSubscription = await marketplace.subscribe(SlotFilled, onSlotFilled) + + # wait for the first slot to be filled + check eventually(slotWasFilled, timeout = expiry.int * 1000) var slotWasFreed = false proc onSlotFreed(event: SlotFreed) = if event.requestId == requestId: slotWasFreed = true + let freedSubscription = await marketplace.subscribe(SlotFreed, onSlotFreed) - let subscription = await marketplace.subscribe(SlotFreed, onSlotFreed) - - # check not freed - await sleepAsync((duration - expiry).int.seconds) + # In 2 periods you cannot have enough invalid proofs submitted: + await sleepAsync(2.periods.int.seconds) check not slotWasFreed - await subscription.unsubscribe() + await filledSubscription.unsubscribe() + await freedSubscription.unsubscribe() # TODO: uncomment once fixed # test "host that submits invalid proofs is paid out less", NodeConfigs( diff --git a/tests/integration/testpurchasing.nim b/tests/integration/testpurchasing.nim index 5da4df08..0968b34f 100644 --- a/tests/integration/testpurchasing.nim +++ b/tests/integration/testpurchasing.nim @@ -56,24 +56,24 @@ twonodessuite "Purchasing", debug1 = false, debug2 = false: let data = await RandomChunker.example(blocks=2) let cid = client1.upload(data).get let id = client1.requestStorage(cid, - duration=100.u256, + duration=10*60.u256, reward=2.u256, proofProbability=3.u256, - expiry=30, + expiry=5*60, collateral=200.u256, nodes=3.uint, tolerance=1.uint).get - check eventually client1.purchaseStateIs(id, "submitted") + check eventually(client1.purchaseStateIs(id, "submitted"), timeout = 3*60*1000) node1.restart() client1.restart() - check eventually client1.purchaseStateIs(id, "submitted") + check eventually(client1.purchaseStateIs(id, "submitted"), timeout = 3*60*1000) let request = client1.getPurchase(id).get.request.get - check request.ask.duration == 100.u256 + check request.ask.duration == (10*60).u256 check request.ask.reward == 2.u256 check request.ask.proofProbability == 3.u256 - check request.expiry == 30 + check request.expiry == (5*60).u256 check request.ask.collateral == 200.u256 check request.ask.slots == 3'u64 check request.ask.maxSlotLoss == 1'u64 diff --git a/tests/integration/testsales.nim b/tests/integration/testsales.nim index 2a57d0f0..b904f405 100644 --- a/tests/integration/testsales.nim +++ b/tests/integration/testsales.nim @@ -60,15 +60,15 @@ twonodessuite "Sales", debug1 = false, debug2 = false: let cid = client2.upload(data).get let id = client2.requestStorage( cid, - duration=10*60.u256, + duration=20*60.u256, reward=400.u256, proofProbability=3.u256, - expiry=5*60, + expiry=10*60, collateral=200.u256, - nodes = 5, - tolerance = 2).get + nodes = 3, + tolerance = 1).get - check eventually(client2.purchaseStateIs(id, "started"), timeout=5*60*1000) + check eventually(client2.purchaseStateIs(id, "started"), timeout=10*60*1000) let updatedAvailability = (client1.getAvailabilities().get).findItem(availability).get check updatedAvailability.totalSize != updatedAvailability.freeSize diff --git a/tests/integration/twonodes.nim b/tests/integration/twonodes.nim index abf20c57..69773c81 100644 --- a/tests/integration/twonodes.nim +++ b/tests/integration/twonodes.nim @@ -43,6 +43,7 @@ template twonodessuite*(name: string, debug1, debug2: string, body) = "--circom-r1cs=tests/circuits/fixtures/proof_main.r1cs", "--circom-wasm=tests/circuits/fixtures/proof_main.wasm", "--circom-zkey=tests/circuits/fixtures/proof_main.zkey", + "--eth-provider=http://127.0.0.1:8545", "--eth-account=" & $account1 ] @@ -67,6 +68,7 @@ template twonodessuite*(name: string, debug1, debug2: string, body) = "--circom-r1cs=tests/circuits/fixtures/proof_main.r1cs", "--circom-wasm=tests/circuits/fixtures/proof_main.wasm", "--circom-zkey=tests/circuits/fixtures/proof_main.zkey", + "--eth-provider=http://127.0.0.1:8545", "--eth-account=" & $account2 ] diff --git a/tests/tools/cirdl/testcirdl.nim b/tests/tools/cirdl/testcirdl.nim index b639be28..a4fd0fc0 100644 --- a/tests/tools/cirdl/testcirdl.nim +++ b/tests/tools/cirdl/testcirdl.nim @@ -14,7 +14,7 @@ suite "tools/cirdl": test "circuit download tool": let circuitPath = "testcircuitpath" - rpcEndpoint = "ws://localhost:8545" + rpcEndpoint = "http://127.0.0.1:8545" marketplaceAddress = Marketplace.address discard existsOrCreateDir(circuitPath) diff --git a/vendor/codex-contracts-eth b/vendor/codex-contracts-eth index 11ccefd7..945f6008 160000 --- a/vendor/codex-contracts-eth +++ b/vendor/codex-contracts-eth @@ -1 +1 @@ -Subproject commit 11ccefd720f1932608b67db95af5b72d73d1257b +Subproject commit 945f6008c8817abd7ca43a40368d33bb1e014c14 diff --git a/vendor/nim-ethers b/vendor/nim-ethers index 0ce6abf0..1ae2cd4a 160000 --- a/vendor/nim-ethers +++ b/vendor/nim-ethers @@ -1 +1 @@ -Subproject commit 0ce6abf0fe942fe7cb1d14b8e4485621be9c3fe8 +Subproject commit 1ae2cd4a35aa7c7ca21ca750fb7f951b3a6a97c0