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

Initialize katana grpc api #2682

Merged
merged 1 commit into from
Nov 13, 2024
Merged
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
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ members = [
"crates/katana/controller",
"crates/katana/core",
"crates/katana/executor",
"crates/katana/grpc",
"crates/katana/node",
"crates/katana/node-bindings",
"crates/katana/pipeline",
Expand Down Expand Up @@ -179,8 +180,8 @@ jsonrpsee = { version = "0.16.2", default-features = false }
lazy_static = "1.4.0"
log = "0.4.21"
metrics = "0.23.0"
num-traits = { version = "0.2", default-features = false }
num-bigint = "0.4.3"
num-traits = { version = "0.2", default-features = false }
once_cell = "1.0"
parking_lot = "0.12.1"
postcard = { version = "1.0.10", features = [ "use-std" ], default-features = false }
Expand Down
15 changes: 15 additions & 0 deletions crates/katana/grpc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
edition.workspace = true
license-file.workspace = true
name = "katana-grpc"
repository.workspace = true
version.workspace = true

[dependencies]
tonic.workspace = true

Comment on lines +8 to +10
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider adding essential gRPC-related dependencies

Ohayo sensei! For a robust gRPC implementation, we should consider adding these common dependencies:

 [dependencies]
 tonic.workspace = true
+prost.workspace = true
+tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
+tonic-types.workspace = true
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[dependencies]
tonic.workspace = true
[dependencies]
tonic.workspace = true
prost.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
tonic-types.workspace = true

[dev-dependencies]

[build-dependencies]
tonic-build.workspace = true
wasm-tonic-build.workspace = true
18 changes: 18 additions & 0 deletions crates/katana/grpc/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::path::PathBuf;

fn main() -> Result<(), Box<dyn std::error::Error>> {
let out_dir =
PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR environment variable not set"));
let feature_client = std::env::var("CARGO_FEATURE_CLIENT");
let feature_server = std::env::var("CARGO_FEATURE_SERVER");

tonic_build::configure()
.build_server(feature_server.is_ok())
.build_client(feature_client.is_ok())
.file_descriptor_set_path(out_dir.join("starknet_descriptor.bin"))
.compile(&["proto/starknet.proto"], &["proto"])?;

println!("cargo:rerun-if-changed=proto");

Ok(())
}
268 changes: 268 additions & 0 deletions crates/katana/grpc/proto/starknet.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
syntax = "proto3";

package starknet;

import "types.proto";

// The Starknet service provides methods for interacting with Starknet.
service Starknet {
// Returns the version of the Starknet JSON-RPC specification being used
rpc SpecVersion(SpecVersionRequest) returns (SpecVersionResponse);

// Get block information with transaction hashes given the block id
rpc GetBlockWithTxHashes(GetBlockRequest) returns (GetBlockWithTxHashesResponse);

// Get block information with full transactions given the block id
rpc GetBlockWithTxs(GetBlockRequest) returns (GetBlockWithTxsResponse);

// Get block information with full transactions and receipts given the block id
rpc GetBlockWithReceipts(GetBlockRequest) returns (GetBlockWithReceiptsResponse);

// Get the information about the result of executing the requested block
rpc GetStateUpdate(GetBlockRequest) returns (GetStateUpdateResponse);

// Get the value of the storage at the given address and key
rpc GetStorageAt(GetStorageAtRequest) returns (GetStorageAtResponse);

// Gets the transaction status
rpc GetTransactionStatus(GetTransactionStatusRequest) returns (GetTransactionStatusResponse);

// Get the details and status of a submitted transaction
rpc GetTransactionByHash(GetTransactionByHashRequest) returns (GetTransactionByHashResponse);

// Get the details of a transaction by a given block id and index
rpc GetTransactionByBlockIdAndIndex(GetTransactionByBlockIdAndIndexRequest) returns (GetTransactionByBlockIdAndIndexResponse);

// Get the transaction receipt by the transaction hash
rpc GetTransactionReceipt(GetTransactionReceiptRequest) returns (GetTransactionReceiptResponse);

// Get the contract class definition in the given block associated with the given hash
rpc GetClass(GetClassRequest) returns (GetClassResponse);

// Get the contract class hash in the given block for the contract deployed at the given address
rpc GetClassHashAt(GetClassHashAtRequest) returns (GetClassHashAtResponse);

// Get the contract class definition in the given block at the given address
rpc GetClassAt(GetClassAtRequest) returns (GetClassAtResponse);

// Get the number of transactions in a block given a block id
rpc GetBlockTransactionCount(GetBlockRequest) returns (GetBlockTransactionCountResponse);

// Call a starknet function without creating a Starknet transaction
rpc Call(CallRequest) returns (CallResponse);

// Estimate the fee for Starknet transactions
rpc EstimateFee(EstimateFeeRequest) returns (EstimateFeeResponse);

// Estimate the L2 fee of a message sent on L1
rpc EstimateMessageFee(EstimateMessageFeeRequest) returns (EstimateFeeResponse);

// Get the most recent accepted block number
rpc BlockNumber(BlockNumberRequest) returns (BlockNumberResponse);

// Get the most recent accepted block hash and number
rpc BlockHashAndNumber(BlockHashAndNumberRequest) returns (BlockHashAndNumberResponse);

// Return the currently configured Starknet chain id
rpc ChainId(ChainIdRequest) returns (ChainIdResponse);

// Returns an object about the sync status, or false if the node is not synching
rpc Syncing(SyncingRequest) returns (SyncingResponse);

// Returns all events matching the given filter
rpc GetEvents(GetEventsRequest) returns (GetEventsResponse);

// Get the nonce associated with the given address in the given block
rpc GetNonce(GetNonceRequest) returns (GetNonceResponse);
}

message SpecVersionRequest {}

message SpecVersionResponse {
string version = 1;
}

message GetBlockRequest {
types.BlockID block_id = 1;
}

message GetBlockWithTxHashesResponse {
oneof result {
types.BlockWithTxHashes block = 1;
types.PendingBlockWithTxHashes pending_block = 2;
}
}

message GetBlockWithTxsResponse {
oneof result {
types.BlockWithTxs block = 1;
types.PendingBlockWithTxs pending_block = 2;
}
}

message GetBlockWithReceiptsResponse {
oneof result {
types.BlockWithReceipts block = 1;
types.PendingBlockWithReceipts pending_block = 2;
}
}

message GetStateUpdateResponse {
oneof result {
types.StateUpdate state_update = 1;
types.PendingStateUpdate pending_state_update = 2;
}
}

message GetStorageAtRequest {
types.BlockID block_id = 1;
types.Felt contract_address = 2;
types.Felt key = 3;
}

message GetStorageAtResponse {
types.Felt value = 1;
}

message GetTransactionStatusRequest {
types.Felt transaction_hash = 1;
}

message GetTransactionStatusResponse {
string finality_status = 1;
string execution_status = 2;
}
Comment on lines +131 to +134
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use Enums Instead of Strings for Status Fields

Ohayo sensei! To enhance type safety and prevent invalid status values, consider using enum types for finality_status and execution_status instead of plain string.

Here's how you can define the enums:

enum FinalityStatus {
  FINALITY_STATUS_UNSPECIFIED = 0;
  FINALITY_STATUS_PENDING = 1;
  FINALITY_STATUS_ACCEPTED_ON_L2 = 2;
  FINALITY_STATUS_ACCEPTED_ON_L1 = 3;
  FINALITY_STATUS_REJECTED = 4;
}

enum ExecutionStatus {
  EXECUTION_STATUS_UNSPECIFIED = 0;
  EXECUTION_STATUS_NOT_RECEIVED = 1;
  EXECUTION_STATUS_RECEIVED = 2;
  EXECUTION_STATUS_PENDING = 3;
  EXECUTION_STATUS_ACCEPTED = 4;
  EXECUTION_STATUS_REJECTED = 5;
}

Then update the message:

 message GetTransactionStatusResponse {
-    string finality_status = 1;
-    string execution_status = 2;
+    FinalityStatus finality_status = 1;
+    ExecutionStatus execution_status = 2;
 }

This change ensures that only valid status values are used and helps with code maintenance.


message GetTransactionByHashRequest {
types.Felt transaction_hash = 1;
}

message GetTransactionByHashResponse {
types.Transaction transaction = 1;
}

message GetTransactionByBlockIdAndIndexRequest {
types.BlockID block_id = 1;
uint64 index = 2;
}

message GetTransactionByBlockIdAndIndexResponse {
types.Transaction transaction = 1;
}

message GetTransactionReceiptRequest {
types.Felt transaction_hash = 1;
}

message GetTransactionReceiptResponse {
types.TransactionReceipt receipt = 1;
}

message GetClassRequest {
types.BlockID block_id = 1;
types.Felt class_hash = 2;
}

message GetClassResponse {
oneof result {
types.DeprecatedContractClass deprecated_contract_class = 1;
types.ContractClass contract_class = 2;
}
}

message GetClassHashAtRequest {
types.BlockID block_id = 1;
types.Felt contract_address = 2;
}

message GetClassHashAtResponse {
types.Felt class_hash = 1;
}

message GetClassAtRequest {
types.BlockID block_id = 1;
types.Felt contract_address = 2;
}

message GetClassAtResponse {
oneof result {
types.DeprecatedContractClass deprecated_contract_class = 1;
types.ContractClass contract_class = 2;
}
}

message GetBlockTransactionCountResponse {
uint64 count = 1;
}

message CallRequest {
types.FunctionCall request = 1;
types.BlockID block_id = 2;
}

message CallResponse {
repeated types.Felt result = 1;
}

message EstimateFeeRequest {
repeated types.Transaction transactions = 1;
repeated string simulation_flags = 2;
types.BlockID block_id = 3;
}

message EstimateFeeResponse {
repeated types.FeeEstimate estimates = 1;
}

message EstimateMessageFeeRequest {
types.MessageFromL1 message = 1;
types.BlockID block_id = 2;
}

message BlockNumberRequest {}

message BlockNumberResponse {
uint64 block_number = 1;
}

message BlockHashAndNumberRequest {}

message BlockHashAndNumberResponse {
types.Felt block_hash = 1;
uint64 block_number = 2;
}

message ChainIdRequest {}

message ChainIdResponse {
string chain_id = 1;
}

message SyncingRequest {}

message SyncingResponse {
oneof result {
bool not_syncing = 1;
types.SyncStatus status = 2;
}
}
Comment on lines +243 to +248
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Clarify the SyncingResponse Structure

Ohayo sensei! The current SyncingResponse uses a oneof to return either a boolean or a SyncStatus. To improve clarity, consider defining a single response that always includes the syncing status.

Here's a possible revision:

message SyncingResponse {
  bool is_syncing = 1;
  types.SyncStatus status = 2;
}

In this structure:

  • When is_syncing is false, the status field can be omitted.
  • When is_syncing is true, the status field provides detailed sync information.

This approach simplifies client-side handling of the response.


message GetEventsRequest {
types.EventFilter filter = 1;
uint32 chunk_size = 2;
string continuation_token = 3;
}

message GetEventsResponse {
repeated types.EmittedEvent events = 1;
string continuation_token = 2;
}

message GetNonceRequest {
types.BlockID block_id = 1;
types.Felt contract_address = 2;
}

message GetNonceResponse {
types.Felt nonce = 1;
}
Loading
Loading