Skip to content

feat: Change proof verification and proposal creation#1641

Merged
bernard-avalabs merged 61 commits intomainfrom
bernard/change-proof-api-v3-part3
Feb 24, 2026
Merged

feat: Change proof verification and proposal creation#1641
bernard-avalabs merged 61 commits intomainfrom
bernard/change-proof-api-v3-part3

Conversation

@bernard-avalabs
Copy link
Contributor

Why this should be merged

Builds on #1638. Verifies a change proof and creates a proposal on the destination trie.

How this works

Mostly follows the implementation from range proofs with some additional checks that are specific to change proofs. The interface for range proofs has a separate function for verify (fwd_range_proof_verify) and verify and propose (fwd_db_verify_range_proof). The change proof interface only has verify, but the comments explains that it also prepares a proposal. I have follow the comment by implementing proof verification and proposal creation in the verify function.

How this was tested

A basic test was added in proofs_test.go that creates a change proof and verifies it and check that it does not return an error. More end-to-end tests will be added in a later PR.

Base automatically changed from bernard/change-proof-api-v3-part2 to main February 13, 2026 03:12
@rkuris
Copy link
Member

rkuris commented Feb 24, 2026

I think this is a lot better, but I think we can even do more here. I'll approve this PR so you can merge it, but we should consider the following for the next release.

I don't like the current split state variables (ChangeProofContext -> VerifiedChangeProofContext -> ProposedChangeProofContext). I think we can do this with a single stateful struct that supports idempotent verification, proposal preparation, commit, and next-range introspection.

I think this simplifies the design a bit, as there are odd edge cases in this design. An example might be that verification is not idempotent. Calling verify again on the same ChangeProofContext returns ProofIsNone because the proof was consumed.

It might make the rust code a tiny bit more complicated but is likely to simplify the ffi interface significantly. I'd have to try it to see.

Maybe something like this:

pub struct ChangeProofContext<'db> {
    proof: FrozenChangeProof,

    // Cached verification context to support idempotent verify calls.
    verification: Option<VerificationContext>,

    // Proposal/commit lifecycle state.
    proposal_state: ProposalState<'db>,
}

struct VerificationContext {
    start_root: HashKey,
    end_root: HashKey,
    start_key: Option<Box<[u8]>>,
    end_key: Option<Box<[u8]>>,
    max_length: Option<NonZeroUsize>,
}

enum ProposalState<'db> {
    // No prepared proposal yet.
    Unprepared,

    // Proposal prepared against a DB snapshot, not committed yet.
    Proposed(crate::ProposalHandle<'db>),

    // Already committed; value is resulting root (None => empty trie).
    Committed(Option<HashKey>),
}

Copy link
Member

@rkuris rkuris left a comment

Choose a reason for hiding this comment

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

Approved with suggestions to make this better (perhaps create another ticket, or abandon this one).

@bernard-avalabs
Copy link
Contributor Author

bernard-avalabs commented Feb 24, 2026

Maybe something like this:

pub struct ChangeProofContext<'db> {
    proof: FrozenChangeProof,

    // Cached verification context to support idempotent verify calls.
    verification: Option<VerificationContext>,

    // Proposal/commit lifecycle state.
    proposal_state: ProposalState<'db>,
}

struct VerificationContext {
    start_root: HashKey,
    end_root: HashKey,
    start_key: Option<Box<[u8]>>,
    end_key: Option<Box<[u8]>>,
    max_length: Option<NonZeroUsize>,
}

enum ProposalState<'db> {
    // No prepared proposal yet.
    Unprepared,

    // Proposal prepared against a DB snapshot, not committed yet.
    Proposed(crate::ProposalHandle<'db>),

    // Already committed; value is resulting root (None => empty trie).
    Committed(Option<HashKey>),
}

I'll merge the current PR and will create a new issue to address your new feedback. (Update: #1709)

Perhaps we can discuss your new interface suggestion in person, as it seems very similar to the interface I had in my initial implementation.

@bernard-avalabs bernard-avalabs merged commit 8a91fbd into main Feb 24, 2026
48 checks passed
@bernard-avalabs bernard-avalabs deleted the bernard/change-proof-api-v3-part3 branch February 24, 2026 20:43
bernard-avalabs added a commit that referenced this pull request Feb 26, 2026
## Why this should be merged

Builds on #1641. This is likely
the last in the current series of Change Proof PRs. It implements
`fwd_db_verify_and_commit_change_proof` and
`fwd_change_proof_find_next_key`.

## How this works

Mostly follows the implementation from range proofs with some additional
checks that are specific to change proofs. The find next key approach is
the same basic one used in range proofs and should later be replaced.

## How this was tested

Added end-to-end tests for committing a change proof, applying multiple
rounds of change proofs with different start keys determined by calling
find next key, and testing change proofs with deletes instead of just
puts.
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.

3 participants