-
Notifications
You must be signed in to change notification settings - Fork 59
feat: specify compact mining-transaction snapshot proofs #175
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
Open
PastaPastaPasta
wants to merge
8
commits into
dashpay:master
Choose a base branch
from
PastaPastaPasta:platform-compact-quorum-proof
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
2c315fc
feat: add DIP for Compact Quorum Proof Chains
PastaPastaPasta e378afa
docs: add Dash Core RPC methods, clarify P2P vs RPC communication
PastaPastaPasta fa0fc4e
docs: simplify RPC/P2P interfaces per review feedback
PastaPastaPasta b82325b
docs(dip): specify mining-only snapshot proof format
PastaPastaPasta 6dfb54d
docs: describe quorum proofs without draft compatibility history
PastaPastaPasta db23bb9
docs: require final quorum certificate checks
PastaPastaPasta 1295a09
docs(dip): describe on-demand historical proof construction
PastaPastaPasta b24d999
docs: clarify compact proof construction semantics
PastaPastaPasta File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,333 @@ | ||
| <pre> | ||
| DIP: pasta-compact-quorum-proofs | ||
| Title: Compact Quorum Proof Chains for Trustless Platform Verification | ||
| Author(s): PastaPastaPasta | ||
| Special-Thanks: | ||
| Comments-Summary: No comments yet. | ||
| Status: Draft | ||
| Type: Standard | ||
| Created: 2026-01-17 | ||
| License: MIT License | ||
| </pre> | ||
|
|
||
| ## Table of Contents | ||
|
|
||
| 1. [Abstract](#abstract) | ||
| 1. [Motivation](#motivation) | ||
| 1. [Protocol Foundations](#protocol-foundations) | ||
| 1. [Trust Model](#trust-model) | ||
| 1. [Wire Format](#wire-format) | ||
| 1. [Verification](#verification) | ||
| 1. [Construction and Serving](#construction-and-serving) | ||
| 1. [SDK Integration](#sdk-integration) | ||
| 1. [Size and Resource Limits](#size-and-resource-limits) | ||
| 1. [Security Considerations](#security-considerations) | ||
| 1. [Copyright](#copyright) | ||
|
|
||
| ## Abstract | ||
|
|
||
| This proposal authenticates current Dash Core quorum keys and EvoNode records from | ||
| an application-supplied trusted snapshot. A relay provides ordinary ChainLock | ||
| certificates, quorum mining transactions, and Merkle paths. The SDK verifies them | ||
| locally before verifying Platform responses. Relays supply evidence and do not | ||
| supply trusted keys. The proof uses existing Dash blocks, commitments, signatures, | ||
| and consensus rules. | ||
|
|
||
| Each handoff authenticates the next quorum through its mining transaction. | ||
| When the mining block lacks a usable ChainLock, a later certificate authenticates | ||
| that block through consecutive X11 headers. | ||
|
|
||
| ## Motivation | ||
|
|
||
| An SDK can distribute a small, fixed Core snapshot and network addresses with its | ||
| release, then acquire the evidence needed to authenticate newer Platform quorum | ||
| keys. The intended history window is three to twelve months. The proof and the | ||
| SDK verifier both contribute to download cost, so they must be measured together. | ||
|
|
||
| ## Protocol Foundations | ||
|
|
||
| [DIP-0004](dip-0004.md) commits simplified masternode lists in coinbase transactions. | ||
| [DIP-0006](dip-0006.md) defines LLMQ commitments and | ||
| [DIP-0008](dip-0008.md) defines ChainLocks. | ||
|
|
||
| A mining transaction contains the complete next quorum commitment. A handoff | ||
| authenticates that transaction with a Merkle path to a ChainLock-authenticated | ||
| block. The final coinbase supplies the quorum and masternode roots used to | ||
| authenticate the requested records. | ||
|
|
||
| ## Trust Model | ||
|
|
||
| The application independently fixes a snapshot containing: | ||
|
|
||
| * Network (0 mainnet, 1 testnet). | ||
| * Core height and block hash. | ||
| * Simplified masternode-list Merkle root. | ||
| * Active quorum-list Merkle root. | ||
|
|
||
| A response MUST exactly match this snapshot. A relay-provided snapshot MUST NOT | ||
| be promoted to trusted configuration merely because a proof is internally valid. | ||
| A successfully verified target can serve as the next session checkpoint. | ||
|
|
||
| This proposal supports mainnet and testnet only. Devnet and regtest are outside | ||
| its scope. | ||
|
|
||
| The design assumes historically authenticated ChainLock quorums do not sign false | ||
| certificates, including after leaving the active set. It proves a sequence of | ||
| statements by authenticated quorum keys. It does **not** independently reconstruct | ||
| DKG, full Core consensus, or the exact active signing-quorum selection for each | ||
| certificate. Membership of a key is not proof of its current signing authority. | ||
| These are deliberate constraints of this compact certificate trust model. | ||
|
|
||
| ## Wire Format | ||
|
|
||
| All proof framing integers are unsigned little-endian fixed-width integers. | ||
| Hashes are 32 bytes in Core serialization order, reversed from RPC display hex. | ||
| Nested transactions and commitments use their existing canonical Core consensus | ||
| serialization, including CompactSize where consensus requires it. There is no | ||
| protobuf or general-purpose object encoding on the proof wire. | ||
|
|
||
| A `blob` is `length:u32 || bytes[length]`. A `path` is: | ||
|
|
||
| ```text | ||
| index:u32 | leaf_count:u32 | sibling_count:u8 | siblings[32]... | ||
| ``` | ||
|
|
||
| A `certificate` is exactly 180 bytes: | ||
|
|
||
| ```text | ||
| height:u32 | core_block_header[80] | Basic_BLS_signature[96] | ||
| ``` | ||
|
|
||
| The main proof is: | ||
|
|
||
| ```text | ||
| magic[8] = ASCII "DASHNC02" | ||
| snapshot { | ||
| network:u8 | height:u32 | block_hash[32] | ||
| masternode_root[32] | quorum_root[32] | ||
| } | ||
| seed_commitment:blob | seed_membership:path | ||
| handoff_count:u16 | ||
| handoffs[handoff_count] { | ||
| certificate | ||
| mining_transaction:blob | transaction_membership:path | ||
| ancestor_count:u16 | ancestor_headers[80]... | ||
| } | ||
| final_certificate | ||
| final_coinbase:blob | coinbase_membership:path | ||
| ``` | ||
|
|
||
| The seed is the complete final quorum commitment, including its vector hash and | ||
| **both** embedded signatures. Its double-SHA256 hash is opened in the snapshot's | ||
| quorum root. Embedded commitment signatures are included in the authenticated | ||
| serialization; this verifier does not re-execute their DKG validation. | ||
|
|
||
| Ancestor headers are ordered oldest first: mining block, then its descendants, | ||
| ending at the certificate's parent. Zero ancestors means the certificate signs | ||
| the mining block itself. The mining height equals certificate height minus | ||
| ancestor count. There is no independent relay-selected mining height. | ||
|
|
||
| The HTTP bootstrap envelope adds authenticated consensus records: | ||
|
|
||
| ```text | ||
| proof:blob | ||
| record_count:u8 | ||
| records[record_count] { | ||
| kind:u8 # 0 quorum commitment; 1 simplified masternode entry | ||
| consensus_leaf:blob | ||
| membership:path | ||
| } | ||
| ``` | ||
|
|
||
| A quorum leaf is the full commitment. A masternode leaf is exactly the | ||
| `CSimplifiedMNListEntry::CalcHash` preimage, excluding the network-only version | ||
| prefix. The decoder must consume the complete supported canonical serialization; | ||
| ambiguous or unsupported masternode encodings are rejected. | ||
|
|
||
| ## Verification | ||
|
|
||
| 1. Enforce all framing limits before allocation. Reject truncation, trailing | ||
| bytes, unknown tags, and a magic value other than `DASHNC02`. | ||
| 2. Require exact equality with the application's trusted snapshot. The snapshot | ||
| MUST be after v20 activation on mainnet or testnet; the proof uses Basic BLS | ||
| signatures and v3 coinbase payloads. | ||
| 3. Parse the seed commitment canonically, require a nonzero subgroup-valid public | ||
| key, and verify its membership in the snapshot quorum root. | ||
| 4. For each handoff, require a strictly increasing certificate height and the | ||
| network's ChainLock quorum type (2 mainnet, 1 testnet). Verify its Basic BLS | ||
| signature using the current key and Dash's existing ChainLock request/signing | ||
| hash construction, including the certificate height, quorum identity, and X11 | ||
| block hash. | ||
| 5. Starting at that signed header, check every `hashPrevBlock` against the X11 | ||
| hash of the preceding supplied header. Verify the complete mining transaction | ||
| against the oldest header's transaction root. Transaction index must be | ||
| nonzero. Require a canonical v3 quorum-commitment transaction with no inputs, | ||
| outputs, or locktime, payload version 1, and the derived mining height. | ||
| 6. Parse its full non-null commitment and install the authenticated next key. | ||
| Reject a handoff to the same quorum identity. A verifier may accept a mining | ||
| block that precedes the initial snapshot, provided the certificate height still | ||
| advances beyond it. Core proof construction may impose a narrower search window | ||
| when selecting bridges; that is a serving limitation, not a wire-format rule. | ||
| 7. Require the final certificate height to strictly exceed the last handoff's | ||
| certificate height, or the trusted snapshot height when there are no handoffs, | ||
| including when the caller's minimum target height is zero. Require the last | ||
| key's commitment to have the network's ChainLock quorum type (2 mainnet, | ||
| 1 testnet), and verify the final certificate's Basic BLS signature using that | ||
| key and the request/signing hash construction in step 4. Open transaction | ||
| index zero, parse its complete v3 coinbase, and require coinbase payload height | ||
| to equal the signed height. Extract both final roots. | ||
| 8. Enforce the caller's minimum target height. Verify every requested record's | ||
| double-SHA256 leaf hash against its corresponding final root. Require the | ||
| requested Platform quorum type and hash to match the authenticated commitment. | ||
| 9. Publish the new state, key, and eligible EvoNode endpoints only after the entire | ||
| envelope succeeds. Then verify the Platform response signature and GroveDB | ||
| proof before returning application data or advancing Platform freshness state. | ||
|
|
||
| Merkle verification consumes exactly the tree depth implied by leaf count. An | ||
| odd final node must use its own hash as the duplicate sibling. Equal siblings at | ||
| non-duplicate positions are rejected. Transaction and record leaves of exactly | ||
| 64 bytes are rejected to prevent interpreting an internal tree node as a leaf. | ||
|
|
||
| ## Construction and Serving | ||
|
|
||
| Core reads historical evidence from block files on demand. ChainLock code locates | ||
| coinbase-carried certificates using exponential search followed by binary search: | ||
| consensus requires the certified height to never decrease, and a non-null | ||
| certificate cannot be followed by a null one. The existing mined-commitment | ||
| database identifies quorum mining blocks; their transactions and Merkle paths | ||
| are read and constructed as needed. No additional persistent index or startup | ||
| scan is required. A bounded certificate cache lasts for one RPC request. | ||
|
|
||
| Construction uses a fixed view of the active chain. Disk reads and proof | ||
| verification run outside the main chain lock; existing quorum database queries | ||
| take short locks. Before returning, Core checks that the target certificate's | ||
| carrier remains on the active chain. A conflicting reorganization requires a | ||
| retry. Missing or pruned block data causes an explicit error rather than being | ||
| interpreted as an absent certificate. Proof-serving nodes should retain the | ||
| historical blocks needed by their supported checkpoints. | ||
|
|
||
| Construction works backwards from the requested target signer to a quorum present | ||
| in the initial snapshot. For each needed quorum, the node locates its mining | ||
| transaction and a usable certificate at or after mining. Searching nearby | ||
| certificates minimizes serialized bytes per height advanced; the search can | ||
| expand when a nearby ChainLock is unavailable. This heuristic is not part of | ||
| verification or a claim of global minimum size. Construction fails explicitly if | ||
| history, a bridge, or the resource budget is unavailable. Multiple bounded | ||
| requests can advance a checkpoint over longer gaps. | ||
|
|
||
| The Core RPC is: | ||
|
|
||
| ```text | ||
| getquorumproofchain checkpoint_hash height=0 quorum_hash="" llmq_type=0 node_count=4 | ||
| ``` | ||
|
|
||
| `height=0` chooses the latest usable ChainLock at the current chain tip. The | ||
| signature may already be known to the live ChainLock manager before a later | ||
| coinbase carries it. A positive height is a minimum: the node searches for a | ||
| certificate at or above | ||
| both it and snapshot height plus one. `quorum_hash` and `llmq_type` request one | ||
| quorum opening; `node_count` requests zero through fifteen eligible EvoNodes. | ||
| The result contains `proof_hex`, `bootstrap_hex`, and `target`. The bootstrap | ||
| field is empty if no records were requested. Generation supports mainnet/testnet. | ||
|
|
||
| ```text | ||
| verifyquorumproofchain checkpoint_object proof_hex minimum_height=0 | ||
| ``` | ||
|
|
||
| The verification RPC takes all independently trusted snapshot fields and returns | ||
| `valid` plus either the authenticated `target` or an `error`. It does not consult | ||
| RPC metadata to obtain trust roots. | ||
|
|
||
| DAPI and quorum servers expose the same relay interface: | ||
|
|
||
| ```http | ||
| POST /proofs | ||
| Content-Type: application/json | ||
|
|
||
| {"checkpoint":"<RPC block hash>","height":1549547, | ||
| "quorumHash":"<RPC quorum hash>","llmqType":6,"nodeCount":4} | ||
| ``` | ||
|
|
||
| Success is the binary bootstrap envelope with content type | ||
| `application/octet-stream`; HTTP gzip compression is permitted. Servers bound | ||
| request sizes, concurrent Core workers, cached bytes, and cache lifetime. | ||
| A timeout does not release a worker permit while its blocking RPC is still | ||
| running. Failure returns an HTTP error, never trusted fallback keys. | ||
|
|
||
| ## SDK Integration | ||
|
|
||
| Mainnet/testnet network builders use the verified provider by default. Release | ||
| snapshots and untrusted seed addresses are embedded. Proof sources can be seeded | ||
| EvoNodes, quorum servers, or an explicitly supplied list of either. Authenticated | ||
| EvoNode records add connection candidates; addresses themselves never confer | ||
| signing authority. | ||
|
|
||
| Verified SDK operation requires reachable proof-serving endpoints backed by | ||
| index-enabled Core nodes. | ||
|
|
||
| The synchronous Platform verifier reports a typed missing-quorum condition. The | ||
| SDK asynchronously obtains a bootstrap proof, verifies it, then repeats the | ||
| complete Platform verification. This applies to reads and transaction results, | ||
| and works without synchronous network calls in browser verification code. | ||
|
|
||
| Applications can explicitly select trusted mode or supply their own context | ||
| provider. Trusted mode obtains quorum keys from its configured provider and skips | ||
| the additional Core bootstrap proof download and verification; Platform response | ||
| proof verification remains separately configurable. Failed verified mode MUST NOT | ||
| silently become trusted mode. | ||
|
|
||
| ## Size and Resource Limits | ||
|
|
||
| | Item | Maximum | | ||
| | --- | ---: | | ||
| | Decoded proof or bootstrap HTTP response | 1,048,576 bytes | | ||
| | Certificates, including final certificate | 4,096 | | ||
| | Ancestor headers across the whole proof | 4,096 | | ||
| | Merkle leaf count | 100,000 | | ||
| | Merkle siblings | 17 | | ||
| | Transaction blob | 100,000 bytes | | ||
| | Seed commitment blob | 1,024 bytes | | ||
| | Bootstrap records | 16 | | ||
| | Record leaf | 4,096 bytes | | ||
|
|
||
| These limits bound individual requests, not the duration of history. Certificate | ||
| availability and quorum cadence determine achievable history per request. | ||
|
|
||
| Real testnet history encoded by the reference implementation measured | ||
| 85,827 / 159,536 / 314,357 gzip bytes for 90 / 180 / 366 days respectively. | ||
| The shared short cross-implementation fixture is 3,469 raw proof bytes, or 4,506 | ||
| raw bytes with one quorum and one EvoNode opening. These are testnet observations, | ||
| not mainnet measurements or worst-case guarantees. Final record openings add to | ||
| the history-only figures. HTTP compression is a transport optimization and does | ||
| not change verification. | ||
|
|
||
| The release requirement is less than 500,000 additional SDK download bytes. | ||
| A standalone verifier artifact cannot establish the integrated SDK delta; compare | ||
| matching release targets and compression settings before shipping a release. | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| An attacker controlling all relays can withhold evidence, replay sufficiently | ||
| recent valid evidence, or exhaust a client's bounded request budget. Successful | ||
| verification establishes authenticity under the trust model, not that the target | ||
| is the globally newest block. Platform signed-time/height freshness policy and | ||
| caller minimum heights are required. Unauthenticated metadata must not advance a | ||
| freshness ratchet. | ||
|
|
||
| The design does not protect against compromise of enough historical quorum keys | ||
| to forge this certificate chain. Stronger guarantees require a stronger trust | ||
| model or additional consensus evidence and have different size costs. | ||
|
|
||
| Snapshots are release trust material. Their hashes and roots require independent | ||
| release verification and network binding. Updating a snapshot from an unverified | ||
| HTTP response defeats the design. Persistent caches, if implemented, require the | ||
| same provenance and integrity protections as their original trust configuration. | ||
|
|
||
| No headers are treated as authenticated merely because a matching quorum key is | ||
| known. Every accepted statement is covered by the certificate chain under the | ||
| historical quorum honesty assumption above. Full state validity and exact signer | ||
| eligibility are deliberately outside this proof's statement. | ||
|
|
||
| ## Copyright | ||
|
|
||
| Copyright (c) 2026 PastaPastaPasta. Licensed under the MIT License. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Reject unsigned mining-height underflow.
Lines [127-128] derive the mining height with unsigned subtraction. Require
ancestor_count <= certificate.heightbefore calculating the height. Otherwise malformed inputs can wrap to a largeu32value and produce inconsistent verifier behavior.🤖 Prompt for AI Agents