Published Date: 2024-10-01 Specs: Authors: Compatibility:
- Backwards-compatible
- Forwards-compatible
Table of Contents
- Summary
- Motivation
- Reference-level explanation
- Compatibility
- Drawbacks
- Rationale and alternatives
- Prior art
- Unresolved questions
- Future possibilities
Summary
Proposes a new commitment scheme for REST Batch Query API results and the process of opening (verifying) such commitments.Motivation
When a user queries data, we want to establish an unbreakable cryptographic commitment that allows the user to hold every party in the supply chain accountable for veracity of the result. This accountability should persist long after the response is provided, so that participants can process data fast in “optimistic” fashion, and can verify and dispute the results later. This mechanism in future will allow us to build automatic dispute resolution mechanisms within the ODF network that financially penalize malicious actors.Requirements
- Hiding - Commitment should not reveal any information about the operation.
- Binding - It should be impossible to change any inputs or outputs of the operation without invalidating the commitment.
- Succinct - Commitment itself should be small enough to e.g. store on-chain, and the process of disputing the operation results should not require storing and transferring the resulting data.
- Deterministic - Same query should result in the same commitment as long as the query itself is deterministic.
- Reproducible - Given all the same inputs of the operation a third party should be able to repeat the query, arrive at the same results, and be able to successfully validate them against the original commitment.
- Reproducibility will be the primary way of verifying the commitments for now, until we introduce zero-knowledge computation proofs.
- Non-repudiable - A prover cannot dispute performing the operation. There exists a mechanism that ties its identity to the provided commitment. This mechanism may be separate from the commitment itself to keep the latter pure zero-knowledge.
- Composable - It should be possible to split computation into several steps and compose their commitments into one final commitment. When joining two datasets from different owners the entire execution may be split into sub-plans that are executed by different nodes belonging to different parties. In the event of a dispute, we should be able to assign responsibility to the specific party and not just stop at the party that performed the final result aggregation.
- Multi-protocol - Ideally the commitment structure can be reused without significant alterations in other protocols like Blockchain Oracle, Flight SQL, Kafka egress, WebSockets etc.
Current API
Our initial attempt to add a resemblance of cryptographic commitments to the REST Batch Query API looked like this:resultHash and state properties.
- Hiding - NO
statereveals in plain text what datasets were queried.
- Binding - NO
- Commitment does not cover the inputs like
query,aliasesand other parameters likedataFormat, row limits etc. - Commitment does not cover outputs like
schema
- Commitment does not cover the inputs like
- Succinct - YES
- Deterministic - YES
- Reproducible - NO
- The
stateinformation allows the user to run the query on the same exact input data - But the query itself is not part of the commitment. This creates a loophole: when the result is disputed, a node operator can claim that this result was provided for a slightly different query than what the user is showing.
- The
- Non-repudiable - NO
- There is no mechanism that ties the result to a node that executed it.
- Composable - NO
- Multi-protocol - NO
Commitments in the ODF Oracle
Although purely in REST API context this attempt looked like a failure, it actually provided a good starting point for ODF Oracle commitments on the blockchain.- Hiding - NO
- The entire request and response data is publicly available, but this is an inherent limitation of non-ZK blockchains
- Binding - YES
- All inputs and outputs are immutably stored on-chain
- Succinct - YES / NO
- All response data ends up stored which we cannot avoid, but the commitment itself does not add much overhead
- Deterministic - YES
- Reproducible - YES
- Original query with all of its parameters is stored on-chain and can be repeated against the
stateinformation in response
- Original query with all of its parameters is stored on-chain and can be repeated against the
- Non-repudiable - YES
- Automatically achieved as the provider signs the response transaction with its private key
- Composable - NO
- Multi-protocol - NO
Need for REST Commitments
As you can see, in combination with properties added by blockchain, the existing API fulfills the oracle use case pretty well. However, now we are starting to work with clients that require commitments from REST API alone. This is, for example, important in the scenario where ODF nodes are used to provide factual data to LLM chatbots - the calling party will interact only with REST API and needs to have an ability to store the commitment in the conversation history.Reference-level explanation
Structured Recursive Commitments
commitment block is redundant and the caller could compute all hashes themselves. In fact they have to do so to validate the response (see below). We include this block purely to:
- Protect clients from implementing hashing in a way that is not consistent with the specification
- Provide more information during the validation and dispute stages to isolate inconsistencies to specific parts.
JSON Hashing
Note that the proposed scheme involves hashing JSON objects. To exclude variations like whitespace characters and property order differences between JSON library implementations we need to convert it into canonical form as specified in RFC 8785: JSON Canonicalization Scheme.Response Validation
Immediately upon receiving the response the caller must validate it to ensure that the commitment is not bogus and is disputable:- Verify that
proof.verificationMethodDID belongs to the node you are requesting data from - Verify
commitment.outputHashby re-computing the hash - Verify
commitment.inputHashby re-computing the hash - Verify
commitment.subQueriesHashby re-computing the hash - Verify the signature in
proof.proofValueusing- Message:
canonicalize(commitment) - Public key:
key_from_did(proof.verificationMethod)
- Message:
- Repeat the steps 3-5 recursively for every entry in
subQueries
Storing Commitments
To be able to dispute the result in future, consumer should store the following fields:inputsubQueriescommitmentproof
input- provides reproducibilitycommitment- seals the response against tamperingproof- adds non-repudiation via signaturesubQueries- provide the above for multi-party computations
Dispute Resolution
The procedure of resolving a dispute using a commitment via reproducibility is as follows:- Consumer submits a claim to the verifier by providing:
inputcommitmentsubQueriesproof
- Verifier obtains the relevant
input.datasets - Verifier validates the claim according to the same rules as described in Response Validation
- If any check fails the claim is rejected as invalid
- Verifier checks that all
authorityspecified insubQueriesare registered nodes- If an unregistered node is found the claim is accepted and the blame is assigned to the root
authorityfor using a bogus node for computing part of the response
- If an unregistered node is found the claim is accepted and the blame is assigned to the root
- Verifier generates the logical query plan and checks that the plan is identical or equivalent to the plan composed from the
subQueries- If plan does not correspond to the original query the claim is accepted and the blame is assigned to the root
authorityfor providing a malicious query plan
- If plan does not correspond to the original query the claim is accepted and the blame is assigned to the root
- In a bottom-up fashion Verifier repeats all the computation steps using
inputand compares hashes of outputs to those captured incommitment.outputHash- If a hash doesn’t match the claim is accepted and the blame is assigned to the corresponding
authorityfor providing a malicious output data
- If a hash doesn’t match the claim is accepted and the blame is assigned to the corresponding
Requirements Checklist
- Hiding - YES / NO
- The hashes in the
commitmentblock can be used as zero-knowledge commitments that do not reveal any information - The
proofreveals the identity of the node performing the computation
- The hashes in the
- Binding - YES
- Deterministic - YES
- Assuming canonical response format
- Reproducible - YES
- Using the
inputfield gives us all the necessary info to reproduce the request
- Using the
- Non-repudiable - YES
- Through the identity and signature in
proof
- Through the identity and signature in
- Composable - YES
- Through
subQueries
- Through
- Multi-protocol - YES
- A similar scheme can be implemented in other protocols e.g. Flight SQL using canonical structs in FlatBuffers format.
Effects on ODF Oracle
Oracle response structure will be modified to include all the elements of the new REST API response. Some of them may be a little redundant: e.g. root-level authority and signature are not needed, because we have the address and transaction signature of the provider. But storing these fields will allow us to use the same dispute resolution mechanism for oracle responses as for other protocols, and avoid the need to map provider addresses to node DIDs on multiple blockchains.Compatibility
The new response structure replaces theresultHash and state properties of the existing REST Batch Query API response, so clients relying on them will need to be updated.
Drawbacks
- Responses become larger and more nested, as they now include the full
inputsection, sub-queries, and the signature block. - Validating a response requires clients to implement JSON canonicalization, hashing, and signature verification.
Rationale and alternatives
HTTP Message Signatures
RFC 9421: HTTP Message Signatures proposes a standard for signing HTTP requests and responses. Under this scheme a query operation could look like this:Signature-Input).
- Hiding - YES / NO
- Depending on the algorithm, signature may reveal the public key of the signer and therefore the identity of a node that provided the response.
- RFC specifies
Content-Digestheader that may be included into the signature instead of the entire payload, thus hiding the response data
- Binding - YES
- Succinct - NO
- The signature itself is small and constant in size, however to dispute the operation a client will have to hold on to the entire response data to show the validity of a signature before verifier attempts to reproduce the request - this would be impractical at scale
- Deterministic - YES
- Assuming stable / canonical response format
- Reproducible - YES
- Note that the response would include the query and all other input parameters, so removing the output fields like
dataandschemagives us all the necessary inputs to reproduce the request
- Note that the response would include the query and all other input parameters, so removing the output fields like
- Non-repudiable - YES
- Through the signature
- Composable - NO
- Including commitments from other nodes that performed parts of the request will require some different mechanism where HTTP signatures are included as parts of the JSON response
- Nodes may not even use HTTP when communicating with one another and use Flight SQL instead.
- Multi-protocol - NO
- This scheme is HTTP specific - other protocols will have to use other methods.
Prior art
- RFC 9421: HTTP Message Signatures - see Rationale and alternatives
- RFC 8785: JSON Canonicalization Scheme - used for hashing JSON objects
- W3C Verifiable Credentials Data Integrity - structure of the
proofblock (type,verificationMethod,proofValue)
Unresolved questions
- Do we need to include a proof that a specific
blockHashactually exists, e.g. by including a signature? Otherwise would it be too easy for a malicious prover to say that the dataset altered its history and they cannot be held accountable for a non-reproducible result? - Checking that the root SQL query corresponds to the
subQueriesplans will be a difficult task, but there doesn’t seem to be an alternative. Even with ZK proofs we will likely hit this problem of computation equivalence.
Future possibilities
- Zero-knowledge proofs are currently very limited in terms of data types and functions they can support, with JOINs being especially problematic. They can be introduced progressively, where possible for simpler queries, as an alternative to verification through signing and reproducibility.
- Commitments can serve as a foundation for automatic dispute resolution in the ODF network that financially penalizes malicious actors.