diff --git a/Cargo.lock b/Cargo.lock index 6003571..f2d79a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -407,6 +407,8 @@ dependencies = [ "prettyplease", "prost", "prost-types", + "pulldown-cmark", + "pulldown-cmark-to-cmark", "regex", "syn", "tempfile", @@ -434,6 +436,26 @@ dependencies = [ "prost", ] +[[package]] +name = "pulldown-cmark" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a14896dfa883796f1cb410461aef38810ea05f2b2c33c5aded3649095fdad" +dependencies = [ + "bitflags", + "memchr", + "unicase", +] + +[[package]] +name = "pulldown-cmark-to-cmark" +version = "22.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50793def1b900256624a709439404384204a5dc3a6ec580281bfaac35e882e90" +dependencies = [ + "pulldown-cmark", +] + [[package]] name = "quote" version = "1.0.45" @@ -508,11 +530,23 @@ name = "sentrix-grpc-wasm" version = "0.1.0-alpha.0" dependencies = [ "hex", + "sentrix-proto", + "tonic", + "tonic-web-wasm-client", +] + +[[package]] +name = "sentrix-proto" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a96198c479e3dad9d7a2718c3d12d86a228cd07a2bade9091ef64206c273c9" +dependencies = [ "prost", + "prost-build", "tonic", + "tonic-build", "tonic-prost", "tonic-prost-build", - "tonic-web-wasm-client", ] [[package]] @@ -761,6 +795,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + [[package]] name = "unicode-ident" version = "1.0.24" diff --git a/Cargo.toml b/Cargo.toml index 119ed22..0a11994 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,14 +14,17 @@ readme = "README.md" crate-type = ["cdylib", "rlib"] [dependencies] +# Proto types come from the published `sentrix-proto` crate (the chain +# repo's source of truth). Drops `tonic-prost` / `prost` from explicit +# deps — they're transitive through `sentrix-proto` now. +# `default-features = false` drops the `transport` feature so this crate +# compiles for the wasm32 target (transport pulls tokio-net / mio which +# don't support wasm). The browser's HTTP layer is `tonic-web-wasm-client` +# anyway, not tonic's hyper-based Channel. +sentrix-proto = { version = "0.1.1", default-features = false } tonic = { version = "0.14", default-features = false, features = ["codegen"] } -tonic-prost = "0.14" tonic-web-wasm-client = "0.9" -prost = "0.14" hex = "0.4" -[build-dependencies] -tonic-prost-build = { version = "0.14", default-features = false } - [lints.rust] unsafe_code = "forbid" diff --git a/build.rs b/build.rs deleted file mode 100644 index 9fc61f2..0000000 --- a/build.rs +++ /dev/null @@ -1,16 +0,0 @@ -// tonic-build invokes protoc at compile time to generate the -// `sentrix.v1` Rust module from `proto/sentrix.proto`. We disable -// server codegen — this crate is browser-only, no need for the -// service stub. - -fn main() -> Result<(), Box> { - // proto/sentrix.proto uses proto3 `optional` (eg - // GetValidatorSetRequest.at_height). protoc 3.15+ accepts this by - // default; ubuntu-22.04 still ships 3.12.4 in apt and needs the - // flag. Harmless on newer protoc. - tonic_prost_build::configure() - .build_server(false) - .protoc_arg("--experimental_allow_proto3_optional") - .compile_protos(&["proto/sentrix.proto"], &["proto"])?; - Ok(()) -} diff --git a/proto/sentrix.proto b/proto/sentrix.proto deleted file mode 100644 index 65c907d..0000000 --- a/proto/sentrix.proto +++ /dev/null @@ -1,256 +0,0 @@ -syntax = "proto3"; - -// Sentrix gRPC service v0.1 — package sentrix.v1. -// -// Parallel transport to JSON-RPC at port 8545. Same backend, same state, -// different wire format. Methods here mirror the most common JSON-RPC paths -// plus add a server-streaming variant for events that JSON-RPC + WebSocket -// can express but at a higher per-subscriber cost. -// -// Versioning: "sentrix.v1" is a hard contract. Breaking changes go to -// "sentrix.v2" with v1 retained for ≥ 2 minor releases overlap. -// -// Status: v0.1 skeleton. Handlers in crates/sentrix-grpc/src/lib.rs return -// tonic::Status::unimplemented until main.rs integration lands. - -package sentrix.v1; - -// 20-byte EVM-compatible address. Mirror of sentrix-primitives::Address. -// Wire = bytes (NOT hex string) for binary efficiency. -message Address { - bytes value = 1; // exactly 20 bytes -} - -// 32-byte hash — block hash, tx hash, state root. -message Hash { - bytes value = 1; // exactly 32 bytes -} - -// Native amount — sentri (10^-8 SRX). u64 wire to match Sentrix internal. -message Amount { - uint64 sentri = 1; -} - -// Block height — u64 starting at 0 (genesis). -message BlockHeight { - uint64 value = 1; -} - -// Mirror of sentrix-primitives::Transaction. Identical wire format to chain -// MDBX serialisation (modulo prost-encoding). Field numbers match the -// canonical struct order; do NOT renumber on changes. -message Transaction { - Hash txid = 1; - Address from_address = 2; - Address to_address = 3; - Amount amount = 4; - Amount fee = 5; - uint64 nonce = 6; - uint64 timestamp = 7; - bytes signature = 8; // 64-byte ed25519 OR 65-byte secp256k1 - bytes payload = 9; // contract calldata (EVM) or staking-op blob - uint32 chain_id = 10; - uint32 tx_type = 11; // 0 = transfer, 1 = contract, 2 = staking-op -} - -message Block { - uint64 index = 1; - Hash hash = 2; - Hash parent_hash = 3; - Hash state_root = 4; - uint64 timestamp = 5; - Address proposer = 6; - uint32 round = 7; - repeated Transaction transactions = 8; - // BFT justification carried from validator-side; included for audit. - // Empty for blocks at h<100_000 (pre state-root-fork). - bytes justification = 9; -} - -message Account { - Address address = 1; - Amount balance = 2; - uint64 nonce = 3; - // For contract accounts: 32-byte storage root + non-empty code_hash. - Hash storage_root = 4; - Hash code_hash = 5; -} - -// Server-streaming event types. -message ChainEvent { - oneof event { - BlockFinalized block_finalized = 1; - PendingTx pending_tx = 2; - ValidatorSetChange validator_set_change = 3; - LogEmitted log = 4; - // Synthetic Lagged sentinel — emitted when the per-subscriber broadcast - // channel drops oldest events (slow consumer). Mirrors tokio broadcast - // RecvError::Lagged semantics. Consumer should resync state from RPC. - StreamLagged lagged = 5; - } - uint64 sequence = 100; // monotonic across all events on this stream - uint64 timestamp = 101; // server-wall-clock unix seconds -} - -message BlockFinalized { Block block = 1; } -message PendingTx { Transaction tx = 1; } - -message ValidatorSetChange { - uint32 epoch = 1; - repeated Address active = 2; - repeated Address jailed = 3; -} - -message LogEmitted { - Address contract = 1; - repeated Hash topics = 2; // 0..4 topics per EVM convention - bytes data = 3; - Hash tx_hash = 4; - uint64 block_height = 5; - uint32 log_index = 6; -} - -message StreamLagged { - uint64 skipped_count = 1; // events dropped since last delivery -} - -// ──────────────────────────────────────────────────────────── -// Service definition -// ──────────────────────────────────────────────────────────── -service Sentrix { - // Submit a signed transaction to the local mempool. Same semantics as - // JSON-RPC eth_sendRawTransaction for EVM txs, with native fields exposed - // for staking-ops and other native variants. - rpc BroadcastTx(BroadcastTxRequest) returns (BroadcastTxResponse); - - // Fetch a block by height OR by hash. Returns NOT_FOUND if outside the - // local chain window (currently 1000 blocks; older blocks need indexer). - rpc GetBlock(GetBlockRequest) returns (Block); - - // Fetch account balance + nonce. Mirrors eth_getBalance + - // eth_getTransactionCount in a single round-trip. Includes mempool-pending - // nonce so wallets build correct next-tx without an extra call (matches - // the pending-aware nonce behaviour from chain v2.1.57). - rpc GetBalance(GetBalanceRequest) returns (Account); - - // v0.4 read-only state queries — drop the REST `/sentrix_status_extended` - // bridge from the explorer's stats hot path. All three are pure reads - // off `state.read()` snapshots; same lock contention profile as - // GetBlock/GetBalance. - // - // Active validator set + per-validator stake/active/jailed flags. - rpc GetValidatorSet(GetValidatorSetRequest) returns (ValidatorSet); - // Native-token supply snapshot (minted, burned, circulating). - rpc GetSupply(GetSupplyRequest) returns (Supply); - // Pending-tx count + a capped header window for UI display. - rpc GetMempool(GetMempoolRequest) returns (Mempool); - - // Server-streaming chain events. Subscribe once, receive every event type - // until cancel or server restart. Replaces N separate eth_subscribe calls. - // Backpressure: server bounded channel per stream (capacity 4096 — same as - // event_tx in chain). On slow client, server drops OLDEST events and emits - // a StreamLagged sentinel. Client should resync state from RPC. - rpc StreamEvents(StreamEventsRequest) returns (stream ChainEvent); -} - -message BroadcastTxRequest { Transaction tx = 1; } - -message BroadcastTxResponse { - Hash txid = 1; - uint64 mempool_position = 2; // 0-indexed; FIFO ordering UX -} - -message GetBlockRequest { - oneof selector { - BlockHeight height = 1; - Hash hash = 2; - bool latest = 3; // selector == "latest" shorthand - bool finalized = 4; // selector == "finalized" (BFT-finalized head) - } -} - -message GetBalanceRequest { - Address address = 1; - // Snapshot height — read state as-of this block. Default = latest. - // Returns FAILED_PRECONDITION if outside chain window. - optional BlockHeight at_height = 2; -} - -message StreamEventsRequest { - // Filter set — empty = subscribe to all event types. Backend filters - // server-side so the wire only carries matched events. - repeated EventFilter filters = 1; - // Resume from a sequence number (0 = current head). Backend keeps last - // 4096 events in a ring buffer — beyond that, sequence is not resumable - // and the server returns FAILED_PRECONDITION. - uint64 from_sequence = 2; -} - -enum EventFilter { - EVENT_FILTER_UNSPECIFIED = 0; - EVENT_FILTER_BLOCK_FINALIZED = 1; - EVENT_FILTER_PENDING_TX = 2; - EVENT_FILTER_VALIDATOR_SET = 3; - EVENT_FILTER_LOG = 4; -} - -// ──────────────────────────────────────────────────────────── -// v0.4 read-only state-query messages -// ──────────────────────────────────────────────────────────── - -message GetValidatorSetRequest { - // Reserved for at_height historical reads — gated on MDBX snapshot - // isolation (Refactor 5). v0.4 returns the latest finalized set. - optional BlockHeight at_height = 1; -} - -message ValidatorSet { - uint32 epoch = 1; - uint32 active_count = 2; - uint32 total_count = 3; - // Total stake across the active set, in sentri (10^-8 SRX). - uint64 total_active_stake_sentri = 4; - repeated ValidatorEntry validators = 5; -} - -message ValidatorEntry { - Address address = 1; - uint64 stake_sentri = 2; - bool active = 3; - bool jailed = 4; -} - -message GetSupplyRequest { - optional BlockHeight at_height = 1; -} - -message Supply { - // sentri = 10^-8 SRX. Cap is fork-gated (210M pre-fork, 315M post- - // tokenomics-v2 at h=640800); leave conversion to display layer. - uint64 minted_sentri = 1; - uint64 burned_sentri = 2; - uint64 circulating_sentri = 3; // = minted − burned -} - -message GetMempoolRequest { - // Cap returned tx headers; default 100, max 500. Larger windows need - // pagination (deferred). 0 = use server default (100). - uint32 limit = 1; -} - -message Mempool { - // Authoritative pending-tx count. `entries` is capped by `limit`; - // size always reflects the full mempool depth. - uint32 size = 1; - repeated MempoolEntry entries = 2; -} - -message MempoolEntry { - Hash txid = 1; - Address from_address = 2; - Address to_address = 3; - Amount amount = 4; - Amount fee = 5; - uint64 nonce = 6; - uint32 tx_type = 7; -} diff --git a/src/lib.rs b/src/lib.rs index b7985fa..d8075fa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,9 +23,12 @@ #![allow(missing_docs)] #![allow(clippy::doc_lazy_continuation)] -#[allow(clippy::all, clippy::pedantic, dead_code)] +/// Generated tonic + prost types for the `sentrix.v1` schema. Re-export +/// of the `sentrix-proto` crate published from the chain repo, so this +/// crate stays in sync with the server schema without vendoring its +/// own copy. pub mod pb { - tonic::include_proto!("sentrix.v1"); + pub use sentrix_proto::*; } pub mod client;