Skip to content

fix(drive): consolidate historical contract proof verification retry logic#3165

Open
thepastaclaw wants to merge 7 commits intodashpay:v3.1-devfrom
thepastaclaw:fix/verify-contract-history-retry
Open

fix(drive): consolidate historical contract proof verification retry logic#3165
thepastaclaw wants to merge 7 commits intodashpay:v3.1-devfrom
thepastaclaw:fix/verify-contract-history-retry

Conversation

@thepastaclaw
Copy link
Contributor

@thepastaclaw thepastaclaw commented Feb 28, 2026

Issue

When getDataContract is called for a contract with keepsHistory: true, it returns "Data contract not found" even though getDataContractHistory succeeds for the same contract.

Root cause: In verify_contract_v0, when contract_known_keeps_history is None (as it always is from FromProof<GetDataContractRequest>), the code defaults to the non-historical path. If that returns Ok(None) (contract not found on the non-historical path), it never retries with the historical path — it only retried on Err(_).

Changes

Core fix (both verify_contract and verify_contract_return_serialization)

  • Extracted _given_history helpers that perform verification with a known history flag
  • Consolidated retry logic into the entry point: when contract_known_keeps_history is None, retry with keeps_history = true if the first attempt returns Err(_) or Ok((_, None))
  • Removed scattered retry logic from deep inside the function body

Tests

  • Added test_contract_keeps_history_verify_with_unknown_history_flag regression test covering:
    1. None (unknown) — must succeed via retry for historical contracts
    2. Some(true) — direct historical verification
    3. Some(false) — non-historical contract verification
    4. verify_contract_return_serialization with None — parallel path coverage

Validation

  • cargo test -p drive
  • cargo clippy -p drive -- -D warnings

Summary by CodeRabbit

  • New Features

    • Enhanced contract verification with history-aware logic for improved handling of contract data
  • Bug Fixes

    • Improved retry mechanism when contract history status is unknown or unspecified
  • Tests

    • Added regression test for contract verification scenarios with unknown history flags, covering multiple verification paths

…logic

When contract_known_keeps_history is None, any result other than
Ok((hash, Some(contract))) now triggers exactly one retry with
history enabled. Previously, retry logic was scattered across
multiple match arms and several failure paths bypassed it entirely.

Refactored verify_contract_v0 and verify_contract_return_serialization_v0
to extract _given_history helpers containing the pure verification logic,
with retry decisions made solely in the outer functions.

Added regression test: test_contract_keeps_history_verify_with_unknown_history_flag
The previous commit incorrectly restricted retry to Err(_) only,
but Ok(None) from the non-historical path is a legitimate trigger
for historical retry — it means the contract exists in the historical
path, not that it's absent. Restoring the _ catch-all preserves the
original fix from a7fec8b.

Test assertions now require contracts to be returned (not accept None)
for cases where the contract definitely exists, eliminating tautological
acceptance paths.
@github-actions github-actions bot added this to the v3.1.0 milestone Feb 28, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 28, 2026

📝 Walkthrough

Walkthrough

This pull request refactors contract verification logic to be history-aware by introducing conditional verification flows based on a keeps_history flag. A new internal helper function computes verification paths dynamically, and a retry mechanism is added when the history status is unknown, with corresponding test infrastructure to verify the new behavior.

Changes

Cohort / File(s) Summary
History-Aware Verification Logic
packages/rs-drive/src/verify/contract/verify_contract/v0/mod.rs, packages/rs-drive/src/verify/contract/verify_contract_return_serialization/v0/mod.rs
Refactored verification functions to compute keeps_history flag and delegate to new private helpers verify_contract_v0_given_history and verify_contract_return_serialization_v0_given_history. Added retry logic when history status is unknown—if initial verification fails, retry with keeps_history enabled. Consolidated nested conditional branches into unified paths based on history flag; adjusted path/key validation and element deserialization accordingly.
Test Infrastructure & Regression Tests
packages/rs-drive/tests/query_tests.rs
Added public function setup_references_tests_with_keeps_history to parameterize contract setup with history tracking. Refactored setup_references_tests to delegate with keeps_history=false. Introduced regression test test_contract_keeps_history_verify_with_unknown_history_flag covering verification behavior for both historical and non-historical contract paths, plus serialization and proof-verification branches.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A bunny hops through verification's hall,
"Does history matter?" it asks with gall,
Try once, try twice—with flags so bright,
Contracts now shine, both wrong and right!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(drive): consolidate historical contract proof verification retry logic' directly and clearly summarizes the main change: consolidating retry logic for historical contract proof verification.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/rs-drive/tests/query_tests.rs`:
- Around line 4702-4703: Rename the test function
test_contract_keeps_history_verify_with_unknown_history_flag to follow the
repository convention by starting with "should_"; update the function signature
(fn test_contract_keeps_history_verify_with_unknown_history_flag) to a
descriptive name beginning with should_, e.g.
should_contract_keep_history_verify_with_unknown_history_flag, and update any
references or test runners expecting the old name so the test still compiles and
runs.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 78184f6 and f992ab4.

📒 Files selected for processing (3)
  • packages/rs-drive/src/verify/contract/verify_contract/v0/mod.rs
  • packages/rs-drive/src/verify/contract/verify_contract_return_serialization/v0/mod.rs
  • packages/rs-drive/tests/query_tests.rs

@thephez
Copy link
Collaborator

thephez commented Mar 5, 2026

Just ran into this issue and finally ended up here

thephez added a commit to dashpay/platform-tutorials that referenced this pull request Mar 5, 2026
Migrate all contract register/retrieve/update tutorials from legacy
js-dash-sdk (CJS) to evo-sdk (ESM). Adds new variants (binary,
indexed, timestamps, history-retrieve) and works around
sdk.contracts.fetch() returning undefined for keepsHistory contracts
(dashpay/platform#3165).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@thepastaclaw
Copy link
Contributor Author

Thanks for confirming, @thephez! The root cause is that when contract_known_keeps_history is None (which is always the case from FromProof<GetDataContractRequest>), the verification code defaults to the non-historical path. If that path returns Ok(None) (contract not found), it never retried with the historical path — it only retried on Err(_).

This PR consolidates the retry logic so that when the history flag is unknown, it retries with keeps_history = true on both Err and Ok((_, None)), which fixes the issue for contracts with keepsHistory: true.

The PR is currently in draft — will work on getting it reviewed and merged.

@dashpay dashpay deleted a comment from coderabbitai bot Mar 6, 2026
@lklimek
Copy link
Contributor

lklimek commented Mar 6, 2026

Empirical testing of the retry logic

I ran two diagnostic tests against this branch to understand the actual behavior of verify_contract in edge cases. The results challenge some assumptions in the PR description.

Test 1: Non-existent contract with None history flag

Question: Does the retry-on-Ok(None) break the "not found" case for contracts that genuinely don't exist?

Result: ✅ Safe — returns Ok((root_hash, None)) correctly.

The absence proof verifies on both historical and non-historical path queries, so the retry is harmless (though redundant).

Test source
#[test]
fn test_verify_non_existent_contract_with_unknown_history_flag() {
    let (drive, _contract) = setup_references_tests(10, 3334);
    let platform_version = PlatformVersion::latest();
    let fake_contract_id = [255u8; 32];
    let contract_proof = drive
        .prove_contract(fake_contract_id, None, platform_version)
        .expect("expected to get proof for non-existent contract");
    let (_, proof_returned_contract) = Drive::verify_contract(
        contract_proof.as_slice(),
        None,
        false,
        false,
        fake_contract_id,
        platform_version,
    )
    .expect("expected verification to succeed for non-existent contract");
    assert!(
        proof_returned_contract.is_none(),
        "expected None for a non-existent contract, got Some",
    );
}
test tests::test_verify_non_existent_contract_with_unknown_history_flag ... ok

Test 2: Historical contract proof verified with non-historical path

Question: What does verify_contract return when a historical contract's proof is verified with Some(false) (forcing the non-historical path, no retry)?

Result: Ok(Some(contract))verification succeeds and returns the contract.

This contradicts the PR description which states:

If that returns Ok(None) (contract not found on the non-historical path), it never retried with the historical path

In practice, the non-historical path does not return Ok(None) for historical contracts. The conditional proof generated by prove_contract_v0 (via grove_get_proved_path_query_with_conditional) contains enough tree structure information that GroveDB resolves the contract regardless of which path query is used for verification.

Test source
#[test]
fn test_historical_contract_proof_verified_with_non_historical_path() {
    let (drive, contract) = setup_references_tests_with_keeps_history(10, 3334, true);
    let platform_version = PlatformVersion::latest();

    let mut latest_contract = contract.clone();
    latest_contract.set_version(contract.version() + 1);
    drive
        .apply_contract(
            &latest_contract,
            BlockInfo {
                time_ms: 1,
                ..Default::default()
            },
            true,
            StorageFlags::optional_default_as_cow(),
            None,
            platform_version,
        )
        .expect("contract update should be applied");

    let contract_proof = drive
        .prove_contract(latest_contract.id().into_buffer(), None, platform_version)
        .expect("expected to get proof");

    // Force non-historical verification path
    let result = Drive::verify_contract(
        contract_proof.as_slice(),
        Some(false),
        false,
        false,
        latest_contract.id().into_buffer(),
        platform_version,
    );

    match &result {
        Ok((_, Some(c))) => println!("RESULT: Ok(Some(contract)) - version {}", c.version()),
        Ok((_, None)) => println!("RESULT: Ok(None) - contract not found"),
        Err(e) => println!("RESULT: Err({:?})", e),
    }
}
RESULT: Ok(Some(contract)) - version 2
test tests::test_historical_contract_proof_verified_with_non_historical_path ... ok

Implications

Since the non-historical path already succeeds for historical contracts (due to the conditional proof structure), the retry logic added by this PR appears to be dead code in practice — neither Err nor Ok(None) is returned for existing contracts on the first attempt.

This raises the question: what is the actual scenario that triggers the reported "Data contract not found" error? It may not be in verify_contract at all. Could the issue be upstream — e.g., in the gRPC layer, proof generation, or SDK proof handling?

@thepastaclaw could you share reproduction steps or a failing test case that demonstrates the original bug? That would help pinpoint whether verify_contract is the right place for the fix.

🤖 Co-authored by Claudius the Magnificent AI Agent

@thepastaclaw
Copy link
Contributor Author

Great analysis, @lklimek — these tests are exactly what was needed.

Your findings hold up

I traced through the proof generation and verification paths, and I agree with your conclusions:

prove_contract_v0 uses grove_get_proved_path_query_with_conditional, which inspects the actual storage structure at proof time. If the element at the contract root path is a basic_tree, it knows the contract keeps history and generates a proof using fetch_contract_with_history_latest_query. This means the proof always matches the actual storage layout, regardless of what the verifier thinks keeps_history should be.

Your Test 2 confirms the key implication: the conditional proof contains enough tree structure information that GroveDb::verify_query_with_absence_proof can resolve the contract even when queried with the non-historical path. So:

  • The existing retry-on-Err in v3.1-dev → effectively dead code
  • The new retry-on-Ok(None) in this PR → also dead code for existing contracts

Both tests hold because the conditional proof is self-describing — it includes the necessary path information for either query.

Where does this leave the PR?

The code change itself is still cleaner than what's on v3.1-dev — it consolidates the scattered retry logic (two separate retry sites deep in the function body) into a single structured try-retry pattern at the entry point. But the core claim in the PR description — that Ok(None) on the non-historical path was the root cause — is wrong based on your empirical evidence.

The open question

@thephez confirmed encountering the "Data contract not found" error in practice. That error originates from the SDK layer (rs-sdk-ffi / wasm-sdk) when verify_contract returns Ok((_, None)). But your tests show that shouldn't happen for existing contracts through verify_contract.

Possible explanations I haven't ruled out:

  1. SDK/platform version mismatch — older proof generation code might not use the conditional query, producing proofs that genuinely fail on the wrong path
  2. Network-level issue — truncated/corrupted proof bytes in transit
  3. Different code pathin_multiple_contract_proof_form = true uses different queries (fetch_historical_contracts_query vs fetch_non_historical_contracts_query), though the FromProof<GetDataContractRequest> impl passes false
  4. The error is surfacing from a different layer entirely (gRPC, DAPI, or proof metadata validation)

Proposal

I'll update the PR description to accurately reflect that the retry is defensive rather than actively fixing a known triggering condition. The cleanup consolidation is still worthwhile IMO, but the "Data contract not found" report from thephez needs separate investigation to find the actual root cause.

@thephez — could you share more context on when you hit this? Specifically: which SDK (Rust/JS/Swift), which platform version, and whether it was against testnet or a local setup? That would help narrow down where the actual failure is.

@lklimek
Copy link
Contributor

lklimek commented Mar 6, 2026

Correction: bug confirmed, PR is correct

My earlier analysis was wrong. After further testing I can confirm:

The bug is real and reproducible on v3.1-dev

The PR's own test (test_contract_keeps_history_verify_with_unknown_history_flag) fails on v3.1-dev:

RESULT: Ok(None) — CONTRACT NOT FOUND — THIS IS THE BUG
thread 'tests::test_contract_keeps_history_verify_with_unknown_history_flag' panicked:
  contract exists and was updated — None retry must return it
test ... FAILED

Why my earlier tests were misleading

My earlier "Test 2" used Some(false) to force the non-historical path and observed Ok(Some(contract)). This led me to conclude the non-historical path works fine. But Some(false) bypasses the retry logic entirely — it's a different code path than None. When None is passed (the actual SDK path), the behavior on v3.1-dev is:

  1. First attempt with keeps_history = false → GroveDB verifies the proof but returns Ok((root_hash, None)) because the element at key [0] is a tree (not an item)
  2. The existing retry-on-Err at lines 73-86 doesn't trigger because the result is Ok, not Err
  3. The deserialization retry at lines 129-146 also doesn't help — the element was never returned as "found" in the first place
  4. Final result: Ok((root_hash, None)) — contract appears to not exist

The PR correctly fixes this

The PR's refactored approach (extracting _given_history helpers with retry on both Err and Ok((_, None))) addresses the actual root cause. The Ok((_, None)) retry IS essential — it's the only way to catch the case where the non-historical path query finds nothing because the data is stored under the historical tree structure.

Non-existent contracts are safe

A non-existent contract with None correctly returns Ok((_, None)) on both paths — the absence proof verifies successfully regardless of which path query is used. The retry is harmless.

I apologize for the incorrect initial analysis. The PR description was right.

🤖 Co-authored by Claudius the Magnificent AI Agent

in_multiple_contract_proof_form,
contract_id,
platform_version,
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SEC-001 (LOW) — Restore diagnostic context in retry log

The old code logged the original result before retrying:

tracing::debug!(?path_query, error=?e, "retrying contract verification with history enabled");

The new code only logs contract_id, losing the original result and path query context that helps diagnose verification issues.

Suggestion: log the original result at debug level before retrying:

tracing::debug!(?contract_id, ?result, "retrying contract verification with history enabled");

🤖 Claudius

proof_contract_4.expect("contract exists — return_serialization must return it");
assert_eq!(latest_contract, deserialized);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PROJ-001 (LOW) — Add test for non-existent contract with None history flag

The test covers the happy path (historical contract exists, None triggers successful retry) but does not cover the opposite: a contract ID that genuinely does not exist with contract_known_keeps_history=None.

Empirical testing confirms this case is safe (absence proof verifies on both paths, retry returns Ok((_, None)) correctly), but an explicit test would prevent regressions if the retry logic changes:

#[test]
fn test_verify_non_existent_contract_with_unknown_history_flag() {
    let (drive, _contract) = setup_references_tests(10, 3334);
    let platform_version = PlatformVersion::latest();
    let fake_contract_id = [255u8; 32];
    let contract_proof = drive
        .prove_contract(fake_contract_id, None, platform_version)
        .expect("expected to get proof for non-existent contract");
    let (_, proof_returned_contract) = Drive::verify_contract(
        contract_proof.as_slice(),
        None,
        false,
        false,
        fake_contract_id,
        platform_version,
    )
    .expect("expected verification to succeed for non-existent contract");
    assert!(
        proof_returned_contract.is_none(),
        "expected None for a non-existent contract, got Some",
    );
}

No such test exists in the codebase.

🤖 Claudius

}

#[test]
fn test_contract_keeps_history_verify_with_unknown_history_flag() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PROJ-002 (LOW) — Test does not verify retry was actually exercised

Test 1 asserts the end result is correct but doesn't prove the retry path was taken. If a GroveDb change made non-historical queries accidentally succeed on historical proofs, this test would still pass while the retry logic becomes dead code.

Consider capturing the tracing debug log ("retrying contract verification with history enabled") via tracing-test subscriber and asserting it was emitted exactly once.

🤖 Claudius

let (proof_root_hash, proof_contract) = Drive::verify_contract(
contract_proof.as_slice(),
None,
false,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PROJ-003 (INFO) — No coverage for in_multiple_contract_proof_form=true

All four sub-cases use in_multiple_contract_proof_form=false. The verify_contracts (plural) function calls verify_contract with (None, true, true) — so this retry path is used in production but not directly tested by this PR or anywhere else in the test suite. Consider adding a test with true, or testing verify_contracts with a historical contract.

🤖 Claudius

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/rs-drive/tests/query_tests.rs (1)

926-966: ⚠️ Potential issue | 🟠 Major

Add #[cfg(feature = "server")] guard to setup_references_tests_with_keeps_history.

The helper at line 926 uses symbols that are only imported behind #[cfg(feature = "server")]: setup_drive, DriveConfig, Drive, GroveDbOpBatch, setup_contract, and add_init_contracts_structure_operations. Without a matching guard on the function itself, this will fail to compile when the server feature is disabled. The wrapper function setup_references_tests above it is already guarded; the new helper should be too.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rs-drive/tests/query_tests.rs` around lines 926 - 966, Add the same
feature-gate attribute used for the wrapper to the helper: put #[cfg(feature =
"server")] immediately above the setup_references_tests_with_keeps_history
function declaration so that symbols like setup_drive, DriveConfig, Drive,
GroveDbOpBatch, setup_contract, and add_init_contracts_structure_operations are
only referenced when the "server" feature is enabled.
🧹 Nitpick comments (2)
packages/rs-drive/src/verify/contract/verify_contract/v0/mod.rs (1)

109-151: Extract the shared proof-shape validator.

This block is now almost identical to packages/rs-drive/src/verify/contract/verify_contract_return_serialization/v0/mod.rs, and the duplication already shows drift: the non-historical error path still says "historical contract". A common helper that validates (path, key, maybe_element) and returns the raw item bytes would keep both verifiers aligned.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rs-drive/src/verify/contract/verify_contract/v0/mod.rs` around lines
109 - 151, Extract a shared helper (e.g., validate_proved_element or
extract_proved_contract_bytes) that takes (path, key, maybe_element,
contract_id, keeps_history, platform_version) and encapsulates the proof-shape
validation and byte extraction currently duplicated in
verify_contract::v0::mod.rs: check path against
contract_keeping_history_root_path when keeps_history is true, otherwise check
path == contract_root_path and key == vec![0], return a clear CorruptedProof
error message appropriate to the historical vs non-historical case, convert
maybe_element into item bytes and run DataContract::versioned_deserialize(...,
false, platform_version) returning the deserialized contract or Error; replace
the inline block in verify_contract::v0::mod.rs with a call to this helper and
reuse the same helper from verify_contract_return_serialization::v0::mod.rs to
eliminate duplication and fix the incorrect error text.
packages/rs-drive/tests/query_tests.rs (1)

4702-4813: Prefer separate should_... tests for each verification branch.

This bundles four distinct paths into one test, so a failure won't tell you which branch regressed, and the new name falls outside the repo's convention for new tests.

Based on learnings, new tests in files under tests should start with should …; existing tests can keep their current convention.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/rs-drive/tests/query_tests.rs` around lines 4702 - 4813, The current
test test_contract_keeps_history_verify_with_unknown_history_flag bundles four
verification branches (None, Some(true), Some(false), and
verify_contract_return_serialization(None)) making failures ambiguous; split it
into four focused tests named with the repo convention (e.g.,
should_verify_contract_with_unknown_history_retry,
should_verify_contract_with_explicit_historical,
should_verify_contract_with_explicit_non_historical,
should_return_serialization_with_unknown_history) that each set up only the
needed fixtures (use setup_references_tests_with_keeps_history and separate
non-historical setup for the Some(false) case), call the appropriate functions
(Drive::verify_contract or Drive::verify_contract_return_serialization) for that
single branch, and assert only that branch’s expectations so failures clearly
indicate which path regressed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/rs-drive/tests/query_tests.rs`:
- Around line 926-966: Add the same feature-gate attribute used for the wrapper
to the helper: put #[cfg(feature = "server")] immediately above the
setup_references_tests_with_keeps_history function declaration so that symbols
like setup_drive, DriveConfig, Drive, GroveDbOpBatch, setup_contract, and
add_init_contracts_structure_operations are only referenced when the "server"
feature is enabled.

---

Nitpick comments:
In `@packages/rs-drive/src/verify/contract/verify_contract/v0/mod.rs`:
- Around line 109-151: Extract a shared helper (e.g., validate_proved_element or
extract_proved_contract_bytes) that takes (path, key, maybe_element,
contract_id, keeps_history, platform_version) and encapsulates the proof-shape
validation and byte extraction currently duplicated in
verify_contract::v0::mod.rs: check path against
contract_keeping_history_root_path when keeps_history is true, otherwise check
path == contract_root_path and key == vec![0], return a clear CorruptedProof
error message appropriate to the historical vs non-historical case, convert
maybe_element into item bytes and run DataContract::versioned_deserialize(...,
false, platform_version) returning the deserialized contract or Error; replace
the inline block in verify_contract::v0::mod.rs with a call to this helper and
reuse the same helper from verify_contract_return_serialization::v0::mod.rs to
eliminate duplication and fix the incorrect error text.

In `@packages/rs-drive/tests/query_tests.rs`:
- Around line 4702-4813: The current test
test_contract_keeps_history_verify_with_unknown_history_flag bundles four
verification branches (None, Some(true), Some(false), and
verify_contract_return_serialization(None)) making failures ambiguous; split it
into four focused tests named with the repo convention (e.g.,
should_verify_contract_with_unknown_history_retry,
should_verify_contract_with_explicit_historical,
should_verify_contract_with_explicit_non_historical,
should_return_serialization_with_unknown_history) that each set up only the
needed fixtures (use setup_references_tests_with_keeps_history and separate
non-historical setup for the Some(false) case), call the appropriate functions
(Drive::verify_contract or Drive::verify_contract_return_serialization) for that
single branch, and assert only that branch’s expectations so failures clearly
indicate which path regressed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c208a6b4-9346-43a1-ae9b-f05e50914679

📥 Commits

Reviewing files that changed from the base of the PR and between c3e0a83 and 97c78a9.

📒 Files selected for processing (3)
  • packages/rs-drive/src/verify/contract/verify_contract/v0/mod.rs
  • packages/rs-drive/src/verify/contract/verify_contract_return_serialization/v0/mod.rs
  • packages/rs-drive/tests/query_tests.rs

@thepastaclaw
Copy link
Contributor Author

Thanks for the follow-up, @lklimek — and for running the PR's own test against v3.1-dev to reproduce it directly. That's the definitive confirmation.

Your breakdown of why Some(false) masked the bug is spot on. The None path (which is what the SDK actually uses) is the one that matters, and it clearly fails without the Ok((_, None)) retry.

I should have caught that distinction in my earlier response instead of agreeing that the retry was dead code — lesson learned. The PR description was correct all along.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants