Skip to content
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

Endpoint for querying light blocks. #50

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
5 changes: 5 additions & 0 deletions v2/concordium/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -336,4 +336,9 @@ service Queries {
// a bug.
// * `UNIMPLEMENTED` if the endpoint is disabled on the node.
rpc DryRun (stream DryRunRequest) returns (stream DryRunResponse);

// Get a sequence of finalization proofs and Merkle finalization committee proofs that will
// allow a light client to update its current last finalized block from a trusted start block
// to a specified target block.
rpc GetLightBlocks (LightBlocksRequest) returns (stream LightBlocksItem);
}
50 changes: 50 additions & 0 deletions v2/concordium/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3540,3 +3540,53 @@ message DryRunSuccessResponse {
}
}

// A request from a light client to catch up from a trusted block to a subsequent finalized
// block.
message LightBlocksRequest {
// The highest finalized block currently trusted by the light client.
BlockHashInput from = 1;
// The target finalized block to catch the light client up to.
// The request will fail if this is not descended from the 'from' block.
BlockHashInput to = 2;
// If true, indicates that the light client is not aware of the current epoch finalization
// committee for it's highest finalized block.
bool current_committee_unknown = 3;
// If true, indicates that the light client is not aware of the next epoch finalization
// committee for it's highest finalized block.
bool next_committee_unknown = 4;
// If true, the response should include a proof of the next epoch finalization committee for
// the 'to' block.
bool next_committee_required = 5;
Comment on lines +3551 to +3559
Copy link
Contributor

Choose a reason for hiding this comment

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

Discussion: I am not so sure about having these flags, since they will result in the parsed return type having options for this information, but the user specified whether they are present already.
I find that it is usually better for an API to introduce separate functions instead of flags, since it eliminates the error handling of the option.
Also, do we need this many flags? Maybe we could have a separate entry point, just with a proof of current and next committee for a given block or just always provide them as part of this entrypoint.

}

// Representation of a generic Merkle proof.
// A Merkle proof can be canonically converted to a root hash by converting each of its
// branches to bytes, concatenating them, and then taking the SHA256 hash of the result.
message MerkleProof {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: On top of this, we should probably have new type wrappers for each type of merkle proof that we will expose.

// The branches of the Merkle proof.
repeated MerkleBranch branches = 1;
}

// Branches of a Merkle proof.
// A Merkle branch is either raw data bytes or a sub-Merkle proof.
message MerkleBranch {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggestion: Consider moving this into MerkleProof as a sub-type.

oneof branch {
// Raw data bytes. For this case, 'raw_data' is the representation of the branch
// as bytes.
bytes raw_data = 1;
// A sub-proof. For this case, the root hash of 'sub_proof' is the representation
// of the branch as bytes.
MerkleProof sub_proof = 2;
}
}

// An item produced in response to a `LightBlocksRequest`.
message LightBlocksItem {
oneof item {
// A finalization entry proving that a block is finalized, and checkable knowing
// the finalization committee for the epoch of the block.
EpochFinalizationEntry finalization_entry = 1;
// A Merkle proof of what the next or current epoch finalization committee is for a block.
MerkleProof committee_proof = 2;
}
}
Comment on lines +3584 to +3592
Copy link
Contributor

@limemloh limemloh Jan 4, 2024

Choose a reason for hiding this comment

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

I have been a while since we talked about this, but could we avoid the oneof by making the committee_proof an optional field?
I think this makes more sense, since the committee_proof is tied to a finalization_entry which has to be emitted right before it.

Suggested change
message LightBlocksItem {
oneof item {
// A finalization entry proving that a block is finalized, and checkable knowing
// the finalization committee for the epoch of the block.
EpochFinalizationEntry finalization_entry = 1;
// A Merkle proof of what the next or current epoch finalization committee is for a block.
MerkleProof committee_proof = 2;
}
}
message LightBlocksItem {
// A finalization entry proving that a block is finalized, and checkable knowing
// the finalization committee for the epoch of the block.
EpochFinalizationEntry finalization_entry = 1;
// A Merkle proof of what the next or current epoch finalization committee is for a block.
optional MerkleProof committee_proof = 2;
}