Skip to content

merkledb -- clarify/improve change proof invariants #1810

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 51 additions & 7 deletions x/merkledb/proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,27 +470,71 @@ type KeyChange struct {
Value maybe.Maybe[[]byte]
}

// A change proof proves that a set of key-value changes occurred
// between two trie roots, where each key-value pair's key is
// between some lower and upper bound (inclusive).
type ChangeProof struct {
// Invariant: At least one of [StartProof], [EndProof], or
Copy link
Author

Choose a reason for hiding this comment

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

Technically this is only true once #1772 is merged but that seems kind of imminent

// [KeyChanges] is non-empty.

// If false, the node that created this doesn't have
// sufficient history to generate a change proof and
// all other fields must be empty.
// Otherwise at least one other field is non-empty.
HadRootsInHistory bool

// A proof that the smallest key in the requested range does/doesn't
// exist in the trie with the requested start root.
// Empty if no lower bound on the requested range was given.
// Note that this may not be an entire proof -- nodes are omitted if
// they are also in [EndProof].
StartProof []ProofNode
// A proof that the largest key in [KeyValues] and [DeletedKeys]
// does/doesn't exist in the trie with the requested start root.
// Empty iff no upper bound on the requested range was given
// and [KeyValues] and [DeletedKeys] are empty.

// If [KeyChanges] is non-empty, this is a proof of the largest key
// in [KeyChanges].
//
// If [KeyChanges] is empty and an upper range bound was given,
// this is a proof of the upper range bound.
//
// If [KeyChanges] is empty and no upper range bound was given,
// this is empty.
EndProof []ProofNode
// A subset of key-values that were added, removed, or had their values modified
// between the requested start root (exclusive) and the requested

// A subset of key-values that were added, removed, or had their values
// modified between the requested start root (exclusive) and the requested
// end root (inclusive).
// Sorted by increasing key.
// Each key is in the requested range (inclusive).
// The first key-value is the first key-value at/after the range start.
// The key-value pairs are consecutive. That is, if keys k1 and k2 are
// in [KeyChanges] then there is no k3 that was modified between the start and
// end roots such that k1 < k3 < k2.
// This is a subset of the requested key-value range, rather than the entire
// range, because otherwise the proof may be too large.
// Sorted by increasing key and with no duplicate keys.
//
// Example: Suppose that between the start root and the end root, the following
// key-value pairs were added, removed, or modified:
//
// [kv1, kv2, kv3, kv4, kv5]
// where start <= kv1 < ... < kv5 <= end.
//
// The following are possible values of [KeyChanges]:
//
// []
// [kv1]
// [kv1, kv2]
// [kv1, kv2, kv3]
// [kv1, kv2, kv3, kv4]
// [kv1, kv2, kv3, kv4, kv5]
//
// The following values of [KeyChanges] are always invalid, for example:
//
// [kv2] (Doesn't include kv1, the first key-value at/after the range start)
// [kv1, kv3] (Doesn't include kv2, the key-value between kv1 and kv3)
// [kv1, kv3, kv2] (Not sorted by increasing key)
// [kv1, kv1] (Duplicate key-value pairs)
// [kv0, kv1] (For some kv1 < start)
// [kv1, kv2, kv3, kv4, kv5, kv6] (For some kv6 > end)
KeyChanges []KeyChange
}

Expand Down