2024-12-14 06:07:55 +01:00
|
|
|
from std/times import inMilliseconds, initDuration, inSeconds, fromUnix
|
|
|
|
|
import std/sugar
|
|
|
|
|
import pkg/codex/logutils
|
|
|
|
|
import pkg/questionable/results
|
|
|
|
|
import pkg/ethers/provider
|
|
|
|
|
import ../contracts/time
|
|
|
|
|
import ../contracts/deployment
|
|
|
|
|
import ../codex/helpers
|
|
|
|
|
import ../examples
|
|
|
|
|
import ./marketplacesuite
|
|
|
|
|
import ./nodeconfigs
|
|
|
|
|
|
|
|
|
|
export logutils
|
|
|
|
|
|
|
|
|
|
logScope:
|
|
|
|
|
topics = "integration test validation"
|
|
|
|
|
|
2025-06-18 16:56:05 +02:00
|
|
|
marketplacesuite(name = "Validation", stopOnRequestFail = false):
|
2025-01-24 18:18:00 +01:00
|
|
|
const blocks = 8
|
|
|
|
|
const ecNodes = 3
|
|
|
|
|
const ecTolerance = 1
|
2025-02-20 08:11:06 +01:00
|
|
|
const proofProbability = 1.u256
|
2025-01-24 18:18:00 +01:00
|
|
|
|
|
|
|
|
const collateralPerByte = 1.u256
|
|
|
|
|
const minPricePerBytePerSecond = 1.u256
|
2024-12-14 06:07:55 +01:00
|
|
|
|
|
|
|
|
test "validator marks proofs as missing when using validation groups",
|
|
|
|
|
NodeConfigs(
|
|
|
|
|
# Uncomment to start Hardhat automatically, typically so logs can be inspected locally
|
|
|
|
|
hardhat: HardhatConfig.none,
|
2025-03-06 17:33:40 +11:00
|
|
|
clients: CodexConfigs.init(nodes = 1)
|
|
|
|
|
# .debug() # uncomment to enable console log output
|
|
|
|
|
# .withLogFile()
|
|
|
|
|
# uncomment to output log file to tests/integration/logs/<start_datetime> <suite_name>/<test_name>/<node_role>_<node_idx>.log
|
|
|
|
|
# .withLogTopics("purchases", "onchain")
|
|
|
|
|
.some,
|
2024-12-14 06:07:55 +01:00
|
|
|
providers: CodexConfigs
|
|
|
|
|
.init(nodes = 1)
|
|
|
|
|
.withSimulateProofFailures(idx = 0, failEveryNProofs = 1)
|
|
|
|
|
# .debug() # uncomment to enable console log output
|
2025-06-23 06:04:05 +02:00
|
|
|
.withLogFile()
|
|
|
|
|
# uncomment to output log file to tests/integration/logs/<start_datetime> <suite_name>/<test_name>/<node_role>_<node_idx>.log
|
|
|
|
|
.withLogTopics("sales", "onchain").some,
|
2024-12-14 06:07:55 +01:00
|
|
|
validators: CodexConfigs
|
|
|
|
|
.init(nodes = 2)
|
|
|
|
|
.withValidationGroups(groups = 2)
|
|
|
|
|
.withValidationGroupIndex(idx = 0, groupIndex = 0)
|
|
|
|
|
.withValidationGroupIndex(idx = 1, groupIndex = 1)
|
|
|
|
|
# .debug() # uncomment to enable console log output
|
refactor: debug and logging
- Move test manager values to config object
- Increase codex port separation (between api and disc ports) in an attempt to prevent overlap across tests (ie Test1: api=8000(tcp), disc=9000(udp), and Test2: api=9000(tcp), disc=10000(udp))
- print stderr when exitcode == 1 if there's < 3 lines of stdout
- Logging:
- Always write test manager harness chronicles logs to file, ie testmanager.chronicles.log in the root of the `integration/logs/<run name>` dir
- Always write individual test stdout to file, ie `<test file name>.stdout.log` in the root of the `integration/logs/<run name>/<test file name>` dir
- On error, print stderr to screen and write stderr to file. Or on failure, if stdout is sufficiently short, write stderr to screen and file in `integration/logs/<run name>/<test file name>/<test file name>.stderr.log`
- When debugging, ie DebugCodexNodes == true
- Removes DebugTestHarness from controlling anything other than printing chronicles output from the testmanager to the terminal
- Now, if DebugCodexNodes is set to true:
- Codex node (chronicles) output for multinodesuite tests is logged to file, eg `integration/logs/<run name>/<test file name>/<test name>/<role>_<idx>.log`
- Codex chronicles output is logged to stdout, which also written to file (see above)
2025-03-06 15:49:08 +11:00
|
|
|
# .withLogFile()
|
2024-12-14 06:07:55 +01:00
|
|
|
# uncomment to output log file to tests/integration/logs/<start_datetime> <suite_name>/<test_name>/<node_role>_<node_idx>.log
|
refactor: debug and logging
- Move test manager values to config object
- Increase codex port separation (between api and disc ports) in an attempt to prevent overlap across tests (ie Test1: api=8000(tcp), disc=9000(udp), and Test2: api=9000(tcp), disc=10000(udp))
- print stderr when exitcode == 1 if there's < 3 lines of stdout
- Logging:
- Always write test manager harness chronicles logs to file, ie testmanager.chronicles.log in the root of the `integration/logs/<run name>` dir
- Always write individual test stdout to file, ie `<test file name>.stdout.log` in the root of the `integration/logs/<run name>/<test file name>` dir
- On error, print stderr to screen and write stderr to file. Or on failure, if stdout is sufficiently short, write stderr to screen and file in `integration/logs/<run name>/<test file name>/<test file name>.stderr.log`
- When debugging, ie DebugCodexNodes == true
- Removes DebugTestHarness from controlling anything other than printing chronicles output from the testmanager to the terminal
- Now, if DebugCodexNodes is set to true:
- Codex node (chronicles) output for multinodesuite tests is logged to file, eg `integration/logs/<run name>/<test file name>/<test name>/<role>_<idx>.log`
- Codex chronicles output is logged to stdout, which also written to file (see above)
2025-03-06 15:49:08 +11:00
|
|
|
# .withLogTopics("validator")
|
2024-12-14 06:07:55 +01:00
|
|
|
# each topic as a separate string argument
|
|
|
|
|
.some,
|
|
|
|
|
):
|
|
|
|
|
let client0 = clients()[0].client
|
|
|
|
|
let expiry = 5.periods
|
|
|
|
|
let duration = expiry + 10.periods
|
|
|
|
|
|
|
|
|
|
# let mine a block to sync the blocktime with the current clock
|
|
|
|
|
discard await ethProvider.send("evm_mine")
|
|
|
|
|
|
|
|
|
|
var currentTime = await ethProvider.currentTime()
|
|
|
|
|
let requestEndTime = currentTime.truncate(uint64) + duration
|
|
|
|
|
|
2025-01-24 18:18:00 +01:00
|
|
|
let data = await RandomChunker.example(blocks = blocks)
|
|
|
|
|
let datasetSize =
|
|
|
|
|
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
2025-03-17 17:08:24 -03:00
|
|
|
await createAvailabilities(
|
2025-02-20 08:11:06 +01:00
|
|
|
datasetSize.truncate(uint64),
|
|
|
|
|
duration,
|
|
|
|
|
collateralPerByte,
|
|
|
|
|
minPricePerBytePerSecond,
|
2025-01-24 18:18:00 +01:00
|
|
|
)
|
2024-12-14 06:07:55 +01:00
|
|
|
|
2025-03-17 17:08:24 -03:00
|
|
|
let cid = (await client0.upload(data)).get
|
2024-12-14 06:07:55 +01:00
|
|
|
let purchaseId = await client0.requestStorage(
|
|
|
|
|
cid,
|
|
|
|
|
expiry = expiry,
|
|
|
|
|
duration = duration,
|
2025-01-24 18:18:00 +01:00
|
|
|
nodes = ecNodes,
|
|
|
|
|
tolerance = ecTolerance,
|
2024-12-14 06:07:55 +01:00
|
|
|
proofProbability = proofProbability,
|
|
|
|
|
)
|
2025-03-17 17:08:24 -03:00
|
|
|
let requestId = (await client0.requestId(purchaseId)).get
|
2024-12-14 06:07:55 +01:00
|
|
|
|
|
|
|
|
debug "validation suite", purchaseId = purchaseId.toHex, requestId = requestId
|
|
|
|
|
|
2025-06-18 16:56:05 +02:00
|
|
|
discard await waitForRequestToStart(expiry.int + 60)
|
2024-12-14 06:07:55 +01:00
|
|
|
|
|
|
|
|
discard await ethProvider.send("evm_mine")
|
|
|
|
|
currentTime = await ethProvider.currentTime()
|
|
|
|
|
let secondsTillRequestEnd = (requestEndTime - currentTime.truncate(uint64)).int
|
|
|
|
|
|
|
|
|
|
debug "validation suite", secondsTillRequestEnd = secondsTillRequestEnd.seconds
|
|
|
|
|
|
2025-06-18 16:56:05 +02:00
|
|
|
discard await waitForRequestToFail(secondsTillRequestEnd + 60)
|
2024-12-14 06:07:55 +01:00
|
|
|
|
|
|
|
|
test "validator uses historical state to mark missing proofs",
|
|
|
|
|
NodeConfigs(
|
|
|
|
|
# Uncomment to start Hardhat automatically, typically so logs can be inspected locally
|
|
|
|
|
hardhat: HardhatConfig.none,
|
2025-03-06 17:33:40 +11:00
|
|
|
clients: CodexConfigs.init(nodes = 1)
|
|
|
|
|
# .debug() # uncomment to enable console log output
|
|
|
|
|
# .withLogFile()
|
|
|
|
|
# uncomment to output log file to tests/integration/logs/<start_datetime> <suite_name>/<test_name>/<node_role>_<node_idx>.log
|
|
|
|
|
# .withLogTopics("purchases", "onchain")
|
|
|
|
|
.some,
|
2024-12-14 06:07:55 +01:00
|
|
|
providers: CodexConfigs
|
|
|
|
|
.init(nodes = 1)
|
|
|
|
|
.withSimulateProofFailures(idx = 0, failEveryNProofs = 1)
|
|
|
|
|
# .debug() # uncomment to enable console log output
|
2025-06-23 06:04:05 +02:00
|
|
|
.withLogFile()
|
|
|
|
|
# uncomment to output log file to tests/integration/logs/<start_datetime> <suite_name>/<test_name>/<node_role>_<node_idx>.log
|
|
|
|
|
.withLogTopics("sales", "onchain").some,
|
2024-12-14 06:07:55 +01:00
|
|
|
):
|
|
|
|
|
let client0 = clients()[0].client
|
|
|
|
|
let expiry = 5.periods
|
|
|
|
|
let duration = expiry + 10.periods
|
|
|
|
|
|
|
|
|
|
# let mine a block to sync the blocktime with the current clock
|
|
|
|
|
discard await ethProvider.send("evm_mine")
|
|
|
|
|
|
|
|
|
|
var currentTime = await ethProvider.currentTime()
|
|
|
|
|
let requestEndTime = currentTime.truncate(uint64) + duration
|
|
|
|
|
|
2025-01-24 18:18:00 +01:00
|
|
|
let data = await RandomChunker.example(blocks = blocks)
|
|
|
|
|
let datasetSize =
|
|
|
|
|
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
2025-03-17 17:08:24 -03:00
|
|
|
await createAvailabilities(
|
2025-02-20 08:11:06 +01:00
|
|
|
datasetSize.truncate(uint64),
|
|
|
|
|
duration,
|
|
|
|
|
collateralPerByte,
|
|
|
|
|
minPricePerBytePerSecond,
|
2025-01-24 18:18:00 +01:00
|
|
|
)
|
2024-12-14 06:07:55 +01:00
|
|
|
|
2025-03-17 17:08:24 -03:00
|
|
|
let cid = (await client0.upload(data)).get
|
2024-12-14 06:07:55 +01:00
|
|
|
let purchaseId = await client0.requestStorage(
|
|
|
|
|
cid,
|
|
|
|
|
expiry = expiry,
|
|
|
|
|
duration = duration,
|
2025-01-24 18:18:00 +01:00
|
|
|
nodes = ecNodes,
|
|
|
|
|
tolerance = ecTolerance,
|
2024-12-14 06:07:55 +01:00
|
|
|
proofProbability = proofProbability,
|
|
|
|
|
)
|
2025-03-17 17:08:24 -03:00
|
|
|
let requestId = (await client0.requestId(purchaseId)).get
|
2024-12-14 06:07:55 +01:00
|
|
|
|
|
|
|
|
debug "validation suite", purchaseId = purchaseId.toHex, requestId = requestId
|
|
|
|
|
|
2025-06-18 16:56:05 +02:00
|
|
|
discard await waitForRequestToStart(expiry.int + 60)
|
2025-01-21 21:54:46 +01:00
|
|
|
|
2024-12-14 06:07:55 +01:00
|
|
|
# extra block just to make sure we have one that separates us
|
|
|
|
|
# from the block containing the last (past) SlotFilled event
|
|
|
|
|
discard await ethProvider.send("evm_mine")
|
|
|
|
|
|
|
|
|
|
var validators = CodexConfigs
|
|
|
|
|
.init(nodes = 2)
|
|
|
|
|
.withValidationGroups(groups = 2)
|
|
|
|
|
.withValidationGroupIndex(idx = 0, groupIndex = 0)
|
|
|
|
|
.withValidationGroupIndex(idx = 1, groupIndex = 1)
|
|
|
|
|
# .debug() # uncomment to enable console log output
|
|
|
|
|
.withLogFile()
|
|
|
|
|
# uncomment to output log file to: # tests/integration/logs/<start_datetime> <suite_name>/<test_name>/<node_role>_<node_idx>.log
|
|
|
|
|
.withLogTopics("validator") # each topic as a separate string argument
|
2025-01-21 21:54:46 +01:00
|
|
|
|
2024-12-14 06:07:55 +01:00
|
|
|
failAndTeardownOnError "failed to start validator nodes":
|
|
|
|
|
for config in validators.configs.mitems:
|
|
|
|
|
let node = await startValidatorNode(config)
|
|
|
|
|
running.add RunningNode(role: Role.Validator, node: node)
|
2025-01-21 21:54:46 +01:00
|
|
|
|
2024-12-14 06:07:55 +01:00
|
|
|
discard await ethProvider.send("evm_mine")
|
|
|
|
|
currentTime = await ethProvider.currentTime()
|
|
|
|
|
let secondsTillRequestEnd = (requestEndTime - currentTime.truncate(uint64)).int
|
|
|
|
|
|
|
|
|
|
debug "validation suite", secondsTillRequestEnd = secondsTillRequestEnd.seconds
|
|
|
|
|
|
2025-06-18 16:56:05 +02:00
|
|
|
discard await waitForRequestToFail(secondsTillRequestEnd + 60)
|