diff --git a/Cargo.lock b/Cargo.lock index 0f6544e4..489dd5b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -525,12 +525,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -759,15 +753,14 @@ dependencies = [ "anyhow", "celestia-grpc-macros", "celestia-proto", - "celestia-tendermint", - "celestia-tendermint-proto", "celestia-types", "dotenvy", "hex", "k256", - "pbjson-types", "prost", "serde", + "tendermint", + "tendermint-proto", "thiserror", "tokio", "tonic", @@ -786,17 +779,15 @@ dependencies = [ name = "celestia-proto" version = "0.5.0" dependencies = [ - "celestia-tendermint-proto", - "pbjson", - "pbjson-build", - "pbjson-types", + "bytes", "prost", "prost-build", "prost-types", "protox", "serde", "serde_json", - "tempfile", + "subtle-encoding", + "tendermint-proto", "tonic", "tonic-build", "wasm-bindgen-test", @@ -808,8 +799,6 @@ version = "0.7.1" dependencies = [ "anyhow", "async-trait", - "celestia-tendermint", - "celestia-tendermint-proto", "celestia-types", "dotenvy", "futures", @@ -827,68 +816,16 @@ dependencies = [ "wasm-bindgen-test", ] -[[package]] -name = "celestia-tendermint" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4529cd69c16e0f75b40f87ed281b602d01e99e1ad0a7a5b147ec93e8711001" -dependencies = [ - "bytes", - "celestia-tendermint-proto", - "digest 0.10.7", - "ed25519", - "ed25519-consensus", - "flex-error", - "futures", - "instant", - "k256", - "num-traits", - "once_cell", - "prost", - "prost-types", - "ripemd", - "serde", - "serde_bytes", - "serde_json", - "serde_repr", - "sha2 0.10.8", - "signature", - "subtle", - "subtle-encoding", - "time", - "zeroize", -] - -[[package]] -name = "celestia-tendermint-proto" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "263e3443a0e60c0f5a407a62f2486217a20cd28617cdaa3ec6546d288728b91d" -dependencies = [ - "bytes", - "flex-error", - "num-derive", - "num-traits", - "prost", - "prost-types", - "serde", - "serde_bytes", - "subtle-encoding", - "time", -] - [[package]] name = "celestia-types" version = "0.8.0" dependencies = [ - "base64 0.22.1", + "base64", "bech32", "bitvec", "blockstore", "bytes", "celestia-proto", - "celestia-tendermint", - "celestia-tendermint-proto", "cid", "const_format", "ed25519-consensus", @@ -900,15 +837,15 @@ dependencies = [ "multiaddr", "multihash", "nmt-rs", - "pbjson-types", "prost", - "prost-types", "rand", "ruint", "serde", "serde_json", "serde_repr", "sha2 0.10.8", + "tendermint", + "tendermint-proto", "thiserror", "time", "wasm-bindgen-test", @@ -956,15 +893,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "chrono" -version = "0.4.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" -dependencies = [ - "num-traits", -] - [[package]] name = "cid" version = "0.11.1" @@ -1535,16 +1463,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "eyre" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" -dependencies = [ - "indenter", - "once_cell", -] - [[package]] name = "fastrand" version = "2.2.0" @@ -1602,7 +1520,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c606d892c9de11507fa0dcffc116434f94e105d0bbdc4e405b61519464c49d7b" dependencies = [ - "eyre", "paste", ] @@ -2443,12 +2360,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - [[package]] name = "indexmap" version = "1.9.3" @@ -2594,7 +2505,7 @@ version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be764c8b96cdcd2974655560a1c6542a366440d47c88114894cc20c24317815" dependencies = [ - "base64 0.22.1", + "base64", "futures-channel", "futures-util", "gloo-net", @@ -2645,7 +2556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d5f8f6ddb09312a9592ec9e21a3ccd6f61e51730d9d56321351eff971b0fe55" dependencies = [ "async-trait", - "base64 0.22.1", + "base64", "http-body 1.0.0", "hyper 1.5.1", "hyper-rustls", @@ -2934,7 +2845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4e830fdf24ac8c444c12415903174d506e1e077fbe3875c404a78c5935a8543" dependencies = [ "asynchronous-codec", - "base64 0.22.1", + "base64", "byteorder", "bytes", "either", @@ -3472,8 +3383,6 @@ dependencies = [ "bytes", "celestia-proto", "celestia-rpc", - "celestia-tendermint", - "celestia-tendermint-proto", "celestia-types", "cid", "dashmap 5.5.3", @@ -3500,6 +3409,8 @@ dependencies = [ "serde_json", "smallvec", "tempfile", + "tendermint", + "tendermint-proto", "thiserror", "tokio", "tokio-util", @@ -3518,7 +3429,6 @@ dependencies = [ "anyhow", "blockstore", "celestia-rpc", - "celestia-tendermint", "celestia-types", "console_error_panic_hook", "enum-as-inner", @@ -3533,6 +3443,7 @@ dependencies = [ "serde-wasm-bindgen", "serde_json", "serde_repr", + "tendermint", "thiserror", "time", "tokio", @@ -3918,17 +3829,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "num-integer" version = "0.1.46" @@ -4101,50 +4001,13 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pbjson" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e6349fa080353f4a597daffd05cb81572a9c031a6d4fff7e504947496fcc68" -dependencies = [ - "base64 0.21.7", - "serde", -] - -[[package]] -name = "pbjson-build" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eea3058763d6e656105d1403cb04e0a41b7bbac6362d413e7c33be0c32279c9" -dependencies = [ - "heck 0.5.0", - "itertools 0.13.0", - "prost", - "prost-types", -] - -[[package]] -name = "pbjson-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54e5e7bfb1652f95bc361d76f3c780d8e526b134b85417e774166ee941f0887" -dependencies = [ - "bytes", - "chrono", - "pbjson", - "pbjson-build", - "prost", - "prost-build", - "serde", -] - [[package]] name = "pem" version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.22.1", + "base64", "serde", ] @@ -4980,7 +4843,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.1", + "base64", "rustls-pki-types", ] @@ -5376,7 +5239,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37468c595637c10857701c990f93a40ce0e357cedb0953d1c26c8d8027f9bb53" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures", "httparse", @@ -5556,6 +5419,51 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "tendermint" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37d513ce7f9e41c67ab2dd3d554ef65f36fbcc61745af1e1f93eafdeefa1ce37" +dependencies = [ + "bytes", + "digest 0.10.7", + "ed25519", + "ed25519-consensus", + "flex-error", + "futures", + "k256", + "num-traits", + "once_cell", + "prost", + "ripemd", + "serde", + "serde_bytes", + "serde_json", + "serde_repr", + "sha2 0.10.8", + "signature", + "subtle", + "subtle-encoding", + "tendermint-proto", + "time", + "zeroize", +] + +[[package]] +name = "tendermint-proto" +version = "0.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c81ba1b023ec00763c3bc4f4376c67c0047f185cccf95c416c7a2f16272c4cbb" +dependencies = [ + "bytes", + "flex-error", + "prost", + "serde", + "serde_bytes", + "subtle-encoding", + "time", +] + [[package]] name = "thiserror" version = "1.0.61" @@ -5744,7 +5652,7 @@ dependencies = [ "async-stream", "async-trait", "axum", - "base64 0.22.1", + "base64", "bytes", "h2 0.4.5", "http 1.1.0", diff --git a/Cargo.toml b/Cargo.toml index f69353a9..1f6d68d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,8 @@ celestia-proto = { version = "0.5.0", path = "proto" } celestia-grpc = { version = "0.1.0", path = "grpc" } celestia-rpc = { version = "0.7.1", path = "rpc", default-features = false } celestia-types = { version = "0.8.0", path = "types", default-features = false } -celestia-tendermint = { version = "0.33.0", default-features = false } -celestia-tendermint-proto = "0.33.0" +tendermint = { version = "0.40.0", default-features = false } +tendermint-proto = "0.40.0" libp2p = "0.54.0" nmt-rs = "0.2.1" @@ -23,8 +23,6 @@ prost-types = "0.13.3" # Uncomment to apply local changes #beetswap = { path = "../beetswap" } #blockstore = { path = "../blockstore" } -#celestia-tendermint = { path = "../celestia-tendermint-rs/tendermint" } -#celestia-tendermint-proto = { path = "../celestia-tendermint-rs/proto" } #nmt-rs = { path = "../nmt-rs" } #libp2p = { path = "../../rust-libp2p/libp2p" } #libp2p-core = { path = "../../rust-libp2p/core" } diff --git a/grpc/Cargo.toml b/grpc/Cargo.toml index 7038c079..b2504b87 100644 --- a/grpc/Cargo.toml +++ b/grpc/Cargo.toml @@ -19,16 +19,15 @@ categories = [ ] [dependencies] -celestia-tendermint-proto.workspace = true -celestia-types = { workspace = true, features = [ "tonic" ] } -celestia-proto = { workspace = true, features = [ "tonic" ] } -celestia-tendermint.workspace = true -prost.workspace = true celestia-grpc-macros = { version = "0.1.0", path = "grpc-macros" } +celestia-proto = { workspace = true, features = ["tonic"] } +celestia-types.workspace = true +prost.workspace = true +tendermint-proto.workspace = true +tendermint.workspace = true hex = "0.4.3" k256 = "0.13.4" -pbjson-types = "0.7.0" serde = "1.0.215" thiserror = "1.0.61" tonic = { version = "0.12.3", default-features = false, features = [ diff --git a/grpc/src/client.rs b/grpc/src/client.rs index 4962b582..80ce1a4b 100644 --- a/grpc/src/client.rs +++ b/grpc/src/client.rs @@ -2,18 +2,17 @@ use prost::Message; use tonic::service::Interceptor; use tonic::transport::Channel; +use celestia_grpc_macros::grpc_method; use celestia_proto::celestia::blob::v1::query_client::QueryClient as BlobQueryClient; use celestia_proto::cosmos::auth::v1beta1::query_client::QueryClient as AuthQueryClient; use celestia_proto::cosmos::base::node::v1beta1::service_client::ServiceClient as ConfigServiceClient; use celestia_proto::cosmos::base::tendermint::v1beta1::service_client::ServiceClient as TendermintServiceClient; use celestia_proto::cosmos::tx::v1beta1::service_client::ServiceClient as TxServiceClient; -use celestia_tendermint::block::Block; +use celestia_proto::cosmos::tx::v1beta1::Tx as RawTx; use celestia_types::blob::{Blob, BlobParams, RawBlobTx}; +use celestia_types::block::Block; use celestia_types::state::auth::AuthParams; -use celestia_types::state::Address; -use celestia_types::state::{RawTx, TxResponse}; - -use celestia_grpc_macros::grpc_method; +use celestia_types::state::{Address, TxResponse}; use crate::types::auth::Account; use crate::types::tx::GetTxResponse; diff --git a/grpc/src/error.rs b/grpc/src/error.rs index 9cdb2c7c..a3f35cb7 100644 --- a/grpc/src/error.rs +++ b/grpc/src/error.rs @@ -16,7 +16,7 @@ pub enum Error { /// Tendermint Error #[error(transparent)] - TendermintError(#[from] celestia_tendermint::Error), + TendermintError(#[from] tendermint::Error), /// Celestia types error #[error(transparent)] @@ -24,7 +24,7 @@ pub enum Error { /// Tendermint Proto Error #[error(transparent)] - TendermintProtoError(#[from] celestia_tendermint_proto::Error), + TendermintProtoError(#[from] tendermint_proto::Error), /// Failed to parse gRPC response #[error("Failed to parse response")] diff --git a/grpc/src/types.rs b/grpc/src/types.rs index ead99ebf..4a107ce1 100644 --- a/grpc/src/types.rs +++ b/grpc/src/types.rs @@ -8,8 +8,8 @@ use celestia_proto::cosmos::base::tendermint::v1beta1::{ GetBlockByHeightRequest, GetBlockByHeightResponse, GetLatestBlockRequest, GetLatestBlockResponse, }; -use celestia_tendermint::block::Block; use celestia_types::blob::BlobParams; +use celestia_types::block::Block; use crate::Error; diff --git a/grpc/src/types/auth.rs b/grpc/src/types/auth.rs index 330f13ca..da7aecb8 100644 --- a/grpc/src/types/auth.rs +++ b/grpc/src/types/auth.rs @@ -1,4 +1,3 @@ -use pbjson_types::Any; use prost::{Message, Name}; use celestia_proto::cosmos::auth::v1beta1::{ @@ -9,6 +8,7 @@ use celestia_types::state::auth::{ AuthParams, BaseAccount, ModuleAccount, RawBaseAccount, RawModuleAccount, }; use celestia_types::state::Address; +use tendermint_proto::google::protobuf::Any; use crate::types::make_empty_params; use crate::types::{FromGrpcResponse, IntoGrpcParam}; diff --git a/grpc/src/types/tx.rs b/grpc/src/types/tx.rs index 9297f75d..aa66fcfc 100644 --- a/grpc/src/types/tx.rs +++ b/grpc/src/types/tx.rs @@ -1,7 +1,4 @@ -use std::convert::Infallible; - use k256::ecdsa::{signature::Signer, Signature}; -use pbjson_types::Any; use prost::{Message, Name}; use celestia_proto::cosmos::crypto::secp256k1; @@ -9,12 +6,13 @@ use celestia_proto::cosmos::tx::v1beta1::{ BroadcastTxRequest, BroadcastTxResponse, GetTxRequest as RawGetTxRequest, GetTxResponse as RawGetTxResponse, SignDoc, }; -use celestia_tendermint::public_key::Secp256k1 as VerifyingKey; -use celestia_tendermint_proto::Protobuf; use celestia_types::state::auth::BaseAccount; use celestia_types::state::{ AuthInfo, Fee, ModeInfo, RawTx, RawTxBody, SignerInfo, Sum, Tx, TxResponse, }; +use tendermint::public_key::Secp256k1 as VerifyingKey; +use tendermint_proto::google::protobuf::Any; +use tendermint_proto::Protobuf; use crate::types::{FromGrpcResponse, IntoGrpcParam}; use crate::Error; @@ -102,7 +100,7 @@ pub fn sign_tx( }; let public_key_as_any = Any { type_url: secp256k1::PubKey::type_url(), - value: public_key.encode_to_vec().into(), + value: public_key.encode_to_vec(), }; let auth_info = AuthInfo { @@ -113,11 +111,10 @@ pub fn sign_tx( }], fee: Fee::new(fee, gas_limit), }; - let auth_info_bytes: Result<_, Infallible> = auth_info.encode_vec(); let bytes_to_sign = SignDoc { body_bytes: tx_body.encode_to_vec(), - auth_info_bytes: auth_info_bytes.expect("Result to be Infallible"), + auth_info_bytes: auth_info.clone().encode_vec(), chain_id, account_number: base_account.account_number, } diff --git a/grpc/tests/utils.rs b/grpc/tests/utils.rs index d5c467ca..0ac2acdf 100644 --- a/grpc/tests/utils.rs +++ b/grpc/tests/utils.rs @@ -9,9 +9,9 @@ use tonic::transport::Channel; use tonic::{Request, Status}; use celestia_grpc::GrpcClient; -use celestia_tendermint::crypto::default::ecdsa_secp256k1::SigningKey; -use celestia_tendermint::public_key::Secp256k1 as VerifyingKey; use celestia_types::state::Address; +use tendermint::crypto::default::ecdsa_secp256k1::SigningKey; +use tendermint::public_key::Secp256k1 as VerifyingKey; const CELESTIA_GRPC_URL: &str = "http://localhost:19090"; diff --git a/node-wasm/Cargo.toml b/node-wasm/Cargo.toml index 4c39e14e..8b8a2f20 100644 --- a/node-wasm/Cargo.toml +++ b/node-wasm/Cargo.toml @@ -24,10 +24,10 @@ crate-type = ["cdylib", "rlib"] [target.'cfg(target_arch = "wasm32")'.dependencies] blockstore.workspace = true -celestia-tendermint.workspace = true celestia-types.workspace = true libp2p = { workspace = true, features = ["serde"] } lumina-node.workspace = true +tendermint.workspace = true anyhow = "1.0.86" console_error_panic_hook = "0.1.7" diff --git a/node-wasm/src/error.rs b/node-wasm/src/error.rs index 1de3ad83..d7348bfc 100644 --- a/node-wasm/src/error.rs +++ b/node-wasm/src/error.rs @@ -133,7 +133,7 @@ from_js_value! { from_display! { blockstore::Error, - celestia_tendermint::error::Error, + tendermint::error::Error, libp2p::identity::ParseError, libp2p::multiaddr::Error, lumina_node::node::NodeError, diff --git a/node/Cargo.toml b/node/Cargo.toml index ed0910db..38ba4d8a 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -20,8 +20,6 @@ categories = [ [dependencies] celestia-proto.workspace = true -celestia-tendermint.workspace = true -celestia-tendermint-proto.workspace = true celestia-types.workspace = true libp2p = { workspace = true, features = [ "autonat", @@ -33,6 +31,8 @@ libp2p = { workspace = true, features = [ "kad", ] } prost.workspace = true +tendermint-proto.workspace = true +tendermint.workspace = true async-trait = "0.1.80" beetswap = "0.4.0" diff --git a/node/src/daser.rs b/node/src/daser.rs index 201cdfed..10789183 100644 --- a/node/src/daser.rs +++ b/node/src/daser.rs @@ -33,11 +33,11 @@ use std::cmp::min; use std::collections::HashSet; use std::sync::Arc; -use celestia_tendermint::Time; use futures::future::BoxFuture; use futures::stream::FuturesUnordered; use futures::{FutureExt, StreamExt}; use rand::Rng; +use tendermint::Time; use tokio::select; use tokio_util::sync::CancellationToken; use tracing::{debug, error, warn}; diff --git a/node/src/p2p.rs b/node/src/p2p.rs index 59a228ea..a350604d 100644 --- a/node/src/p2p.rs +++ b/node/src/p2p.rs @@ -21,12 +21,12 @@ use std::time::Duration; use blockstore::Blockstore; use celestia_proto::p2p::pb::{header_request, HeaderRequest}; -use celestia_tendermint_proto::Protobuf; +use celestia_types::fraud_proof::BadEncodingFraudProof; +use celestia_types::hash::Hash; use celestia_types::nmt::{Namespace, NamespacedSha2Hasher}; use celestia_types::row::{Row, RowId}; use celestia_types::row_namespace_data::{RowNamespaceData, RowNamespaceDataId}; use celestia_types::sample::{Sample, SampleId}; -use celestia_types::{fraud_proof::BadEncodingFraudProof, hash::Hash}; use celestia_types::{Blob, ExtendedHeader, FraudProof}; use cid::Cid; use futures::stream::FuturesOrdered; @@ -48,6 +48,7 @@ use libp2p::{ Multiaddr, PeerId, }; use smallvec::SmallVec; +use tendermint_proto::Protobuf; use tokio::select; use tokio::sync::{mpsc, oneshot, watch}; use tokio_util::sync::CancellationToken; @@ -131,7 +132,7 @@ pub enum P2pError { /// ProtoBuf message failed to be decoded. #[error("ProtoBuf decoding error: {0}")] - ProtoDecodeFailed(#[from] celestia_tendermint_proto::Error), + ProtoDecodeFailed(#[from] tendermint_proto::Error), /// An error propagated from [`celestia_types`] that is related to [`Cid`]. #[error("CID error: {0}")] @@ -182,7 +183,7 @@ impl From for P2pError { impl From for P2pError { fn from(value: prost::DecodeError) -> Self { - P2pError::ProtoDecodeFailed(celestia_tendermint_proto::Error::decode_message(value)) + P2pError::ProtoDecodeFailed(tendermint_proto::Error::decode_message(value)) } } diff --git a/node/src/p2p/header_ex/server.rs b/node/src/p2p/header_ex/server.rs index dfddc5d7..c68e9b6a 100644 --- a/node/src/p2p/header_ex/server.rs +++ b/node/src/p2p/header_ex/server.rs @@ -210,9 +210,9 @@ mod tests { use crate::test_utils::{async_test, gen_filled_store}; use celestia_proto::p2p::pb::header_request::Data; use celestia_proto::p2p::pb::StatusCode; - use celestia_tendermint_proto::Protobuf; use celestia_types::ExtendedHeader; use std::future::poll_fn; + use tendermint_proto::Protobuf; use tokio::select; use tokio::sync::oneshot; diff --git a/node/src/p2p/header_ex/utils.rs b/node/src/p2p/header_ex/utils.rs index eedf8e9a..1a394372 100644 --- a/node/src/p2p/header_ex/utils.rs +++ b/node/src/p2p/header_ex/utils.rs @@ -1,9 +1,9 @@ use celestia_proto::p2p::pb::header_request::Data; use celestia_proto::p2p::pb::{HeaderRequest, HeaderResponse, StatusCode}; -use celestia_tendermint_proto::Protobuf; use celestia_types::consts::HASH_SIZE; use celestia_types::hash::Hash; use celestia_types::ExtendedHeader; +use tendermint_proto::Protobuf; use crate::p2p::header_ex::HeaderExError; @@ -88,7 +88,7 @@ pub(super) trait ExtendedHeaderExt { impl ExtendedHeaderExt for ExtendedHeader { fn to_header_response(&self) -> HeaderResponse { HeaderResponse { - body: self.encode_vec().unwrap(), + body: self.clone().encode_vec(), status_code: StatusCode::Ok.into(), } } diff --git a/node/src/pruner.rs b/node/src/pruner.rs index 531b9ddb..0f123341 100644 --- a/node/src/pruner.rs +++ b/node/src/pruner.rs @@ -2,8 +2,8 @@ use std::sync::Arc; use std::time::Duration; use blockstore::Blockstore; -use celestia_tendermint::Time; use celestia_types::ExtendedHeader; +use tendermint::Time; use tokio::select; use tokio_util::sync::CancellationToken; use tracing::{debug, error, warn}; diff --git a/node/src/store.rs b/node/src/store.rs index 251fefe6..6b26a638 100644 --- a/node/src/store.rs +++ b/node/src/store.rs @@ -6,12 +6,12 @@ use std::io::Cursor; use std::ops::{Bound, RangeBounds, RangeInclusive}; use async_trait::async_trait; -use celestia_tendermint_proto::Protobuf; use celestia_types::hash::Hash; use celestia_types::ExtendedHeader; use cid::Cid; use prost::Message; use serde::{Deserialize, Serialize}; +use tendermint_proto::Protobuf; use thiserror::Error; pub use crate::block_ranges::{BlockRange, BlockRanges, BlockRangesError}; diff --git a/node/src/store/indexed_db_store.rs b/node/src/store/indexed_db_store.rs index b7ac8069..3d9fcca5 100644 --- a/node/src/store/indexed_db_store.rs +++ b/node/src/store/indexed_db_store.rs @@ -1,10 +1,8 @@ use std::cell::RefCell; -use std::convert::Infallible; use std::fmt::Display; use std::pin::pin; use async_trait::async_trait; -use celestia_tendermint_proto::Protobuf; use celestia_types::hash::Hash; use celestia_types::ExtendedHeader; use cid::Cid; @@ -14,6 +12,7 @@ use send_wrapper::SendWrapper; use serde::{Deserialize, Serialize}; use serde_wasm_bindgen::{from_value, to_value}; use smallvec::smallvec; +use tendermint_proto::Protobuf; use tokio::sync::Notify; use tracing::warn; use wasm_bindgen::JsValue; @@ -45,6 +44,7 @@ const VERSION_KEY: &str = "version"; struct ExtendedHeaderEntry { // We use those fields as indexes, names need to match ones in `add_index` height: u64, + #[serde(with = "celestia_types::serializers::hash")] hash: Hash, header: Vec, } @@ -593,7 +593,11 @@ async fn insert_tx_op( headers: VerifiedExtendedHeaders, ) -> Result { let head = headers.as_ref().first().expect("headers to not be empty"); - let tail = headers.as_ref().last().expect("headers to not be empty"); + let tail = headers + .as_ref() + .last() + .cloned() + .expect("headers to not be empty"); let header_store = tx.store(HEADER_STORE_NAME)?; let ranges_store = tx.store(RANGES_STORE_NAME)?; @@ -609,11 +613,11 @@ async fn insert_tx_op( verify_against_neighbours( &header_store, prev_exists.then_some(head), - next_exists.then_some(tail), + next_exists.then_some(&tail), ) .await?; - for header in headers.as_ref() { + for header in headers { let hash = header.hash(); let hash_index = header_store.index(HASH_INDEX_NAME)?; let jsvalue_hash_key = KeyRange::only(&to_value(&hash)?).map_err(rexie::Error::IdbError)?; @@ -624,14 +628,11 @@ async fn insert_tx_op( return Err(StoreInsertionError::HashExists(hash).into()); } - // make sure Result is Infallible, we unwrap it later - let serialized_header: std::result::Result<_, Infallible> = header.encode_vec(); - let height = header.height().value(); let header_entry = ExtendedHeaderEntry { height, hash, - header: serialized_header.unwrap(), + header: header.encode_vec(), }; let jsvalue_header = to_value(&header_entry)?; @@ -644,7 +645,7 @@ async fn insert_tx_op( .expect("invalid range"); set_ranges(&ranges_store, HEADER_RANGES_KEY, &header_ranges).await?; - Ok(tail.clone()) + Ok(tail) } async fn update_sampling_metadata_tx_op( @@ -959,7 +960,7 @@ pub mod tests { let header_entry = ExtendedHeaderEntry { height: header.height().value(), hash: header.hash(), - header: header.encode_vec().unwrap(), + header: header.encode_vec(), }; header_store diff --git a/node/src/store/redb_store.rs b/node/src/store/redb_store.rs index 72ac0c43..5221d681 100644 --- a/node/src/store/redb_store.rs +++ b/node/src/store/redb_store.rs @@ -1,11 +1,10 @@ use std::fmt::Display; use std::ops::RangeInclusive; +use std::path::Path; use std::pin::pin; use std::sync::Arc; -use std::{convert::Infallible, path::Path}; use async_trait::async_trait; -use celestia_tendermint_proto::Protobuf; use celestia_types::hash::Hash; use celestia_types::ExtendedHeader; use cid::Cid; @@ -13,6 +12,7 @@ use redb::{ CommitError, Database, ReadTransaction, ReadableTable, StorageError, Table, TableDefinition, TableError, TransactionError, WriteTransaction, }; +use tendermint_proto::Protobuf; use tokio::sync::Notify; use tokio::task::spawn_blocking; use tracing::warn; @@ -270,9 +270,8 @@ impl RedbStore { .map_err(|e| StoreInsertionError::HeadersVerificationFailed(e.to_string()))?; self.write_tx(move |tx| { - let headers = headers.as_ref(); - - let (Some(head), Some(tail)) = (headers.first(), headers.last()) else { + let (Some(head), Some(tail)) = (headers.as_ref().first(), headers.as_ref().last()) + else { return Ok(()); }; @@ -296,9 +295,7 @@ impl RedbStore { for header in headers { let height = header.height().value(); let hash = header.hash(); - // until unwrap_infallible is stabilised, make sure Result is Infallible manually - let serialized_header: Result<_, Infallible> = header.encode_vec(); - let serialized_header = serialized_header.unwrap(); + let serialized_header = header.encode_vec(); if headers_table .insert(height, &serialized_header[..])? @@ -369,8 +366,7 @@ impl RedbStore { }; // make sure Result is Infallible and unwrap it later - let serialized: Result<_, Infallible> = entry.encode_vec(); - let serialized = serialized.unwrap(); + let serialized = entry.encode_vec(); sampling_metadata_table.insert(height, &serialized[..])?; diff --git a/node/src/store/utils.rs b/node/src/store/utils.rs index 01529aea..63beb893 100644 --- a/node/src/store/utils.rs +++ b/node/src/store/utils.rs @@ -1,6 +1,6 @@ -#[cfg(not(target_arch = "wasm32"))] -use celestia_tendermint_proto::Protobuf; use celestia_types::ExtendedHeader; +#[cfg(not(target_arch = "wasm32"))] +use tendermint_proto::Protobuf; use crate::executor::yield_now; use crate::store::Result; diff --git a/node/src/syncer.rs b/node/src/syncer.rs index 7b684345..2801ca81 100644 --- a/node/src/syncer.rs +++ b/node/src/syncer.rs @@ -16,9 +16,9 @@ use std::time::Duration; use backoff::backoff::Backoff; use backoff::ExponentialBackoffBuilder; -use celestia_tendermint::Time; use celestia_types::ExtendedHeader; use serde::{Deserialize, Serialize}; +use tendermint::Time; use tokio::select; use tokio::sync::{mpsc, oneshot}; use tokio_util::sync::CancellationToken; diff --git a/node/tests/node.rs b/node/tests/node.rs index 5cda14f2..ac710121 100644 --- a/node/tests/node.rs +++ b/node/tests/node.rs @@ -2,7 +2,6 @@ use std::time::Duration; -use celestia_tendermint_proto::Protobuf; use celestia_types::consts::appconsts::AppVersion; use celestia_types::consts::HASH_SIZE; use celestia_types::fraud_proof::BadEncodingFraudProof; @@ -18,6 +17,7 @@ use lumina_node::test_utils::{ ExtendedHeaderGeneratorExt, }; use rand::Rng; +use tendermint_proto::Protobuf; use tokio::{select, spawn, sync::mpsc, time::sleep}; use crate::utils::{fetch_bridge_info, new_connected_node}; @@ -264,7 +264,7 @@ fn spawn_befp_announcer(connect_to: Multiaddr) -> mpsc::Sender (), Some(proof) = rx.recv() => { - let proof = proof.encode_vec().unwrap(); + let proof = proof.encode_vec(); announcer.behaviour_mut().gossipsub.publish(topic.hash(), proof).unwrap(); } } diff --git a/proto/Cargo.toml b/proto/Cargo.toml index 22a9e744..1062388f 100644 --- a/proto/Cargo.toml +++ b/proto/Cargo.toml @@ -14,12 +14,12 @@ keywords = ["blockchain", "celestia", "lumina"] categories = ["encoding", "cryptography::cryptocurrencies"] [dependencies] -celestia-tendermint-proto.workspace = true +bytes = { version = "1.0", default-features = false, features = ["serde"]} prost.workspace = true prost-types.workspace = true serde = { version = "1.0.203", features = ["derive"] } -pbjson = { version = "0.7.0", optional = true } -pbjson-types = { version = "0.7.0", optional = true } +subtle-encoding = { version = "0.5", default-features = false, features = ["std", "hex"] } +tendermint-proto.workspace = true tonic = { version = "0.12.3", optional = true, default-features = false, features = [ "codegen", "prost" ]} @@ -28,8 +28,6 @@ tonic = { version = "0.12.3", optional = true, default-features = false, feature prost-build.workspace = true prost-types.workspace = true protox = "0.7.1" -tempfile = { version = "3.13.0", optional = true } -pbjson-build = { version = "0.7.0", optional = true } tonic-build = { version = "0.12.3", default-features = false, optional = true, features = [ "prost" ]} [target.'cfg(not(target_arch = "wasm32"))'.dependencies] @@ -43,4 +41,4 @@ wasm-bindgen-test = "0.3.42" serde_json = "1.0.117" [features] -tonic = [ "dep:tonic", "dep:tonic-build", "dep:pbjson", "dep:pbjson-types", "dep:pbjson-build", "dep:tempfile" ] +tonic = ["dep:tonic", "dep:tonic-build"] diff --git a/proto/build.rs b/proto/build.rs index d8fa4617..233cc8ed 100644 --- a/proto/build.rs +++ b/proto/build.rs @@ -1,24 +1,32 @@ //! A build script generating rust types from protobuf definitions. use prost_types::FileDescriptorSet; +use std::collections::HashSet; +const DEFAULT: &str = r#"#[serde(default)]"#; +const HEXSTRING: &str = r#"#[serde(with = "crate::serializers::bytes::hexstring")]"#; +const VEC_HEXSTRING: &str = r#"#[serde(with = "crate::serializers::bytes::vec_hexstring")]"#; const SERIALIZED: &str = r#"#[derive(::serde::Deserialize, ::serde::Serialize)]"#; const SERIALIZED_DEFAULT: &str = r#"#[derive(::serde::Deserialize, ::serde::Serialize)] #[serde(default)]"#; const TRANSPARENT: &str = r#"#[serde(transparent)]"#; -const BASE64STRING: &str = - r#"#[serde(with = "celestia_tendermint_proto::serializers::bytes::base64string")]"#; -const QUOTED: &str = r#"#[serde(with = "celestia_tendermint_proto::serializers::from_str")]"#; -const VEC_BASE64STRING: &str = - r#"#[serde(with = "celestia_tendermint_proto::serializers::bytes::vec_base64string")]"#; -const OPTION_ANY: &str = r#"#[serde(with = "crate::serializers::option_any")]"#; +const BASE64STRING: &str = r#"#[serde(with = "crate::serializers::bytes::base64string")]"#; +const QUOTED_WITH_DEFAULT: &str = r#"#[serde(with = "crate::serializers::from_str", default)]"#; +const VEC_BASE64STRING: &str = r#"#[serde(with = "crate::serializers::bytes::vec_base64string")]"#; const OPTION_TIMESTAMP: &str = r#"#[serde(with = "crate::serializers::option_timestamp")]"#; +const OPTION_PROTOBUF_DURATION: &str = + r#"#[serde(with = "crate::serializers::option_protobuf_duration")]"#; const NULL_DEFAULT: &str = r#"#[serde(with = "crate::serializers::null_default")]"#; +const BYTES_SKIP_IF_EMPTY: &str = r#"#[serde(skip_serializing_if = "bytes::Bytes::is_empty")]"#; #[rustfmt::skip] static CUSTOM_TYPE_ATTRIBUTES: &[(&str, &str)] = &[ - (".celestia.core.v1.da.DataAvailabilityHeader", SERIALIZED_DEFAULT), (".celestia.blob.v1.MsgPayForBlobs", SERIALIZED_DEFAULT), + (".celestia.core.v1.da.DataAvailabilityHeader", SERIALIZED_DEFAULT), + (".celestia.core.v1.proof.NMTProof", SERIALIZED_DEFAULT), + (".celestia.core.v1.proof.Proof", SERIALIZED_DEFAULT), + (".celestia.core.v1.proof.RowProof", SERIALIZED_DEFAULT), + (".celestia.core.v1.proof.ShareProof", SERIALIZED_DEFAULT), (".cosmos.base.abci.v1beta1.ABCIMessageLog", SERIALIZED_DEFAULT), (".cosmos.base.abci.v1beta1.Attribute", SERIALIZED_DEFAULT), (".cosmos.base.abci.v1beta1.StringEvent", SERIALIZED_DEFAULT), @@ -37,48 +45,75 @@ static CUSTOM_TYPE_ATTRIBUTES: &[(&str, &str)] = &[ (".cosmos.staking.v1beta1.UnbondingDelegation", SERIALIZED_DEFAULT), (".cosmos.staking.v1beta1.UnbondingDelegationEntry", SERIALIZED_DEFAULT), (".header.pb.ExtendedHeader", SERIALIZED_DEFAULT), - (".share.eds.byzantine.pb.BadEncoding", SERIALIZED_DEFAULT), - (".share.eds.byzantine.pb.Share", SERIALIZED_DEFAULT), (".proof.pb.Proof", SERIALIZED_DEFAULT), + (".proto.blob.v1.BlobProto", SERIALIZED), (".shwap.AxisType", SERIALIZED), (".shwap.Row", SERIALIZED), (".shwap.RowNamespaceData", SERIALIZED_DEFAULT), (".shwap.Sample", SERIALIZED_DEFAULT), (".shwap.Share", SERIALIZED_DEFAULT), (".shwap.Share", TRANSPARENT), + + // Celestia's mods + (".tendermint_celestia_mods.types.Block", SERIALIZED), + (".tendermint_celestia_mods.types.Data", SERIALIZED), + (".tendermint_celestia_mods.abci.TimeoutsInfo", SERIALIZED), + (".tendermint_celestia_mods.abci.ResponseInfo", SERIALIZED), ]; #[rustfmt::skip] static CUSTOM_FIELD_ATTRIBUTES: &[(&str, &str)] = &[ - (".celestia.core.v1.da.DataAvailabilityHeader.row_roots", VEC_BASE64STRING), (".celestia.core.v1.da.DataAvailabilityHeader.column_roots", VEC_BASE64STRING), - (".cosmos.base.abci.v1beta1.TxResponse.tx", OPTION_ANY), + (".celestia.core.v1.da.DataAvailabilityHeader.row_roots", VEC_BASE64STRING), + (".celestia.core.v1.proof.NMTProof.leaf_hash", BASE64STRING), + (".celestia.core.v1.proof.NMTProof.nodes", VEC_BASE64STRING), + (".celestia.core.v1.proof.Proof.aunts", VEC_BASE64STRING), + (".celestia.core.v1.proof.Proof.leaf_hash", BASE64STRING), + (".celestia.core.v1.proof.RowProof.root", BASE64STRING), + (".celestia.core.v1.proof.RowProof.row_roots", VEC_HEXSTRING), + (".celestia.core.v1.proof.ShareProof.data", VEC_BASE64STRING), + (".celestia.core.v1.proof.ShareProof.namespace_id", BASE64STRING), (".cosmos.base.abci.v1beta1.TxResponse.logs", NULL_DEFAULT), (".cosmos.base.abci.v1beta1.TxResponse.events", NULL_DEFAULT), (".cosmos.base.query.v1beta1.PageResponse.next_key", BASE64STRING), (".cosmos.staking.v1beta1.RedelegationEntry.completion_time", OPTION_TIMESTAMP), (".cosmos.staking.v1beta1.UnbondingDelegationEntry.completion_time", OPTION_TIMESTAMP), - (".share.eds.byzantine.pb.BadEncoding.axis", QUOTED), - (".proof.pb.Proof.nodes", VEC_BASE64STRING), (".proof.pb.Proof.leaf_hash", BASE64STRING), + (".proof.pb.Proof.nodes", VEC_BASE64STRING), + (".proto.blob.v1.BlobProto.data", BASE64STRING), + (".proto.blob.v1.BlobProto.namespace_id", BASE64STRING), + (".proto.blob.v1.BlobProto.signer", BASE64STRING), (".shwap.RowNamespaceData.shares", NULL_DEFAULT), (".shwap.Share", BASE64STRING), + + // Celestia's mods + (".tendermint_celestia_mods.types.Data.txs", VEC_BASE64STRING), + (".tendermint_celestia_mods.types.Data.hash", HEXSTRING), + (".tendermint_celestia_mods.abci.TimeoutsInfo.timeout_propose", OPTION_PROTOBUF_DURATION), + (".tendermint_celestia_mods.abci.TimeoutsInfo.timeout_commit", OPTION_PROTOBUF_DURATION), + (".tendermint_celestia_mods.abci.ResponseInfo.data", DEFAULT), + (".tendermint_celestia_mods.abci.ResponseInfo.version", DEFAULT), + (".tendermint_celestia_mods.abci.ResponseInfo.app_version", QUOTED_WITH_DEFAULT), + (".tendermint_celestia_mods.abci.ResponseInfo.last_block_height", QUOTED_WITH_DEFAULT), + (".tendermint_celestia_mods.abci.ResponseInfo.last_block_app_hash", DEFAULT), + (".tendermint_celestia_mods.abci.ResponseInfo.last_block_app_hash", BYTES_SKIP_IF_EMPTY), ]; #[rustfmt::skip] static EXTERN_PATHS: &[(&str, &str)] = &[ - (".tendermint", "::celestia_tendermint_proto::v0_34"), - (".google.protobuf.Timestamp", "::celestia_tendermint_proto::google::protobuf::Timestamp"), - (".google.protobuf.Duration", "::celestia_tendermint_proto::google::protobuf::Duration"), - #[cfg(feature = "tonic")] - (".google.protobuf.Any", "::pbjson_types::Any"), + (".google.protobuf.Any", "::tendermint_proto::google::protobuf::Any"), + (".google.protobuf.Duration", "::tendermint_proto::google::protobuf::Duration"), + (".google.protobuf.Timestamp", "::tendermint_proto::google::protobuf::Timestamp"), + (".tendermint", "::tendermint_proto::v0_34"), ]; const PROTO_FILES: &[&str] = &[ "vendor/celestia/blob/v1/params.proto", "vendor/celestia/blob/v1/query.proto", "vendor/celestia/blob/v1/tx.proto", + "vendor/celestia/core/v1/blob/blob.proto", "vendor/celestia/core/v1/da/data_availability_header.proto", + "vendor/celestia/core/v1/proof/proof.proto", "vendor/cosmos/auth/v1beta1/auth.proto", "vendor/cosmos/auth/v1beta1/query.proto", "vendor/cosmos/base/abci/v1beta1/abci.proto", @@ -92,10 +127,18 @@ const PROTO_FILES: &[&str] = &[ "vendor/cosmos/tx/v1beta1/service.proto", "vendor/cosmos/tx/v1beta1/tx.proto", "vendor/go-header/p2p/pb/header_request.proto", + "vendor/go-square/blob/v1/blob.proto", "vendor/header/pb/extended_header.proto", "vendor/share/eds/byzantine/pb/share.proto", "vendor/share/shwap/p2p/bitswap/pb/bitswap.proto", "vendor/share/shwap/pb/shwap.proto", + "vendor/tendermint-celestia-mods/abci/types.proto", + "vendor/tendermint-celestia-mods/blockchain/types.proto", + "vendor/tendermint-celestia-mods/mempool/types.proto", + "vendor/tendermint-celestia-mods/state/types.proto", + "vendor/tendermint-celestia-mods/store/types.proto", + "vendor/tendermint-celestia-mods/types/block.proto", + "vendor/tendermint-celestia-mods/types/types.proto", "vendor/tendermint/types/types.proto", ]; @@ -129,19 +172,20 @@ fn prost_build(fds: FileDescriptorSet) { config.extern_path(proto_path.to_string(), rust_path.to_string()); } + for (proto_path, rust_path) in tendermint_mods_extern_paths(&fds) { + config.extern_path(proto_path, rust_path); + } + config .include_file("mod.rs") - // Comments in Google's protobuf are causing issues with cargo-test - .disable_comments([".google"]) + .enable_type_names() + .bytes([".tendermint_celestia_mods.abci"]) .compile_fds(fds) .expect("prost failed"); } #[cfg(feature = "tonic")] fn tonic_build(fds: FileDescriptorSet) { - let buf_img = tempfile::NamedTempFile::new() - .expect("should be able to create a temp file to hold the buf image file descriptor set"); - let mut prost_config = prost_build::Config::new(); prost_config.enable_type_names(); @@ -151,37 +195,68 @@ fn tonic_build(fds: FileDescriptorSet) { .build_server(false) .client_mod_attribute(".", "#[cfg(not(target_arch=\"wasm32\"))]") .use_arc_self(true) - // override prost-types with pbjson-types .compile_well_known_types(true) - .file_descriptor_set_path(buf_img.path()) - .skip_protoc_run(); + .skip_protoc_run() + .bytes([".tendermint_celestia_mods.abci"]); for (type_path, attr) in CUSTOM_TYPE_ATTRIBUTES { tonic_config = tonic_config.type_attribute(type_path, attr); } + + for (field_path, attr) in CUSTOM_FIELD_ATTRIBUTES { + tonic_config = tonic_config.field_attribute(field_path, attr); + } + for (proto_path, rust_path) in EXTERN_PATHS { tonic_config = tonic_config.extern_path(proto_path, rust_path); } - for (field_path, attr) in CUSTOM_FIELD_ATTRIBUTES { - tonic_config = tonic_config.field_attribute(field_path, attr); + + for (proto_path, rust_path) in tendermint_mods_extern_paths(&fds) { + tonic_config = tonic_config.extern_path(proto_path, rust_path); } tonic_config .compile_fds_with_config(prost_config, fds) .expect("should be able to compile protobuf using tonic"); +} + +/// Create a list of Tentermint messages that needs to be replaced with Celestia's modifications. +fn tendermint_mods_extern_paths(fds: &FileDescriptorSet) -> Vec<(String, String)> { + let mut extern_paths = Vec::new(); + + let tendermint_types = get_proto_types_of(fds, "tendermint"); + let celestia_mods_types = get_proto_types_of(fds, "tendermint_celestia_mods"); + + for mods_type in celestia_mods_types { + let tm_type = mods_type.replace(".tendermint_celestia_mods.", ".tendermint."); + + if tendermint_types.contains(&tm_type) { + let new_extern_path = format!("crate{}", mods_type.replace(".", "::")); + extern_paths.push((tm_type, new_extern_path)); + } + } + + extern_paths +} + +/// Returns the names of all the Protobuf messages of a proto package. +fn get_proto_types_of(fds: &FileDescriptorSet, proto_package: &str) -> HashSet { + let proto_package_prefix = format!("{proto_package}."); + let mut types = HashSet::new(); + + for fd_proto in &fds.file { + let Some(ref pkg_name) = fd_proto.package else { + continue; + }; + + if pkg_name == proto_package || pkg_name.starts_with(&proto_package_prefix) { + for msg in &fd_proto.message_type { + if let Some(ref name) = msg.name { + types.insert(format!(".{pkg_name}.{name}")); + } + } + } + } - let descriptor_set = std::fs::read(buf_img.path()) - .expect("the buf image/descriptor set must exist and be readable at this point"); - - pbjson_build::Builder::new() - .register_descriptors(&descriptor_set) - .unwrap() - .build(&[ - ".celestia_proto", - ".celestia", - ".cosmos", - ".tendermint", - ".google", - ]) - .unwrap(); + types } diff --git a/proto/src/serializers.rs b/proto/src/serializers.rs index d8119ab1..7579e066 100644 --- a/proto/src/serializers.rs +++ b/proto/src/serializers.rs @@ -1,5 +1,8 @@ //! Custom serializers to be used with [`serde`]. +pub mod bytes; +pub mod cow_str; +pub mod from_str; pub mod null_default; -pub mod option_any; +pub mod option_protobuf_duration; pub mod option_timestamp; diff --git a/proto/src/serializers/bytes.rs b/proto/src/serializers/bytes.rs new file mode 100644 index 00000000..aa955b54 --- /dev/null +++ b/proto/src/serializers/bytes.rs @@ -0,0 +1,164 @@ +//! Serialize/deserialize bytes (`Vec`) type + +/// Serialize into hexstring, deserialize from hexstring +pub mod hexstring { + use crate::serializers::cow_str::CowStr; + use serde::{Deserialize, Deserializer, Serializer}; + use subtle_encoding::hex; + + /// Deserialize a hex-encoded string into `Vec` + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let string = Option::::deserialize(deserializer)?.unwrap_or_default(); + hex::decode_upper(&string) + .or_else(|_| hex::decode(&string)) + .map_err(serde::de::Error::custom) + } + + /// Serialize from a byte slice into a hex-encoded string. + pub fn serialize(value: &T, serializer: S) -> Result + where + S: Serializer, + T: AsRef<[u8]>, + { + let hex_bytes = hex::encode_upper(value.as_ref()); + let hex_string = String::from_utf8(hex_bytes).map_err(serde::ser::Error::custom)?; + serializer.serialize_some(&hex_string) + } +} + +/// Serialize into and deserialize from a sequence of _hexstring_. +pub mod vec_hexstring { + use crate::serializers::cow_str::CowStr; + use serde::{Deserialize, Deserializer, Serializer}; + use subtle_encoding::hex; + + /// Deserialize array into `Vec>` + pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + Option::>::deserialize(deserializer)? + .unwrap_or_default() + .into_iter() + .map(|s| hex::decode_upper(s).map_err(serde::de::Error::custom)) + .collect() + } + + /// Serialize from `Vec` into `Vec` + pub fn serialize(value: &[T], serializer: S) -> Result + where + S: Serializer, + T: AsRef<[u8]>, + { + let hexstrings = value + .iter() + .map(|v| { + String::from_utf8(hex::encode_upper(v.as_ref())).map_err(serde::ser::Error::custom) + }) + .collect::, S::Error>>()?; + serializer.serialize_some(&hexstrings) + } +} + +/// Serialize into base64string, deserialize from base64string +pub mod base64string { + use crate::serializers::cow_str::CowStr; + use serde::{Deserialize, Deserializer, Serializer}; + use subtle_encoding::base64; + + /// Deserialize base64string into `Vec` + pub fn deserialize<'de, D, T>(deserializer: D) -> Result + where + D: Deserializer<'de>, + Vec: Into, + { + let s = Option::::deserialize(deserializer)?.unwrap_or_default(); + let v = base64::decode(s).map_err(serde::de::Error::custom)?; + Ok(v.into()) + } + + /// Deserialize base64string into String + pub fn deserialize_to_string<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = Option::::deserialize(deserializer)?.unwrap_or_default(); + String::from_utf8(base64::decode(s).map_err(serde::de::Error::custom)?) + .map_err(serde::de::Error::custom) + } + + /// Serialize from T into base64string + pub fn serialize(value: &T, serializer: S) -> Result + where + S: Serializer, + T: AsRef<[u8]>, + { + let base64_bytes = base64::encode(value.as_ref()); + let base64_string = String::from_utf8(base64_bytes).map_err(serde::ser::Error::custom)?; + serializer.serialize_some(&base64_string) + } +} + +/// Serialize into and deserialize from a sequence of _base64string_. +pub mod vec_base64string { + use crate::serializers::cow_str::CowStr; + use serde::{Deserialize, Deserializer, Serializer}; + use subtle_encoding::base64; + + /// Deserialize array into `Vec>` + pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> + where + D: Deserializer<'de>, + { + Option::>::deserialize(deserializer)? + .unwrap_or_default() + .into_iter() + .map(|s| base64::decode(s).map_err(serde::de::Error::custom)) + .collect() + } + + /// Serialize from `Vec` into `Vec` + pub fn serialize(value: &[T], serializer: S) -> Result + where + S: Serializer, + T: AsRef<[u8]>, + { + let base64_strings = value + .iter() + .map(|v| { + String::from_utf8(base64::encode(v.as_ref())).map_err(serde::ser::Error::custom) + }) + .collect::, S::Error>>()?; + serializer.serialize_some(&base64_strings) + } +} + +/// Serialize into and deserialize from an optional _base64string_. +pub mod option_base64string { + use crate::serializers::cow_str::CowStr; + use serde::{Deserialize, Deserializer, Serializer}; + use subtle_encoding::base64; + + /// Deserialize `Option` into `Vec` or null + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + let s = Option::::deserialize(deserializer)?.unwrap_or_default(); + base64::decode(s).map_err(serde::de::Error::custom) + } + + /// Serialize from `T` into `Option` + pub fn serialize(value: &T, serializer: S) -> Result + where + S: Serializer, + T: AsRef<[u8]>, + { + let base64_bytes = base64::encode(value.as_ref()); + let base64_string = String::from_utf8(base64_bytes).map_err(serde::ser::Error::custom)?; + serializer.serialize_some(&base64_string) + } +} diff --git a/proto/src/serializers/cow_str.rs b/proto/src/serializers/cow_str.rs new file mode 100644 index 00000000..2e1a8fa2 --- /dev/null +++ b/proto/src/serializers/cow_str.rs @@ -0,0 +1,172 @@ +//! Wrapper `Cow<'_, str>` for deserializing without allocation. +//! +//! This is a workaround for [serde's issue 1852](https://github.com/serde-rs/serde/issues/1852). + +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; +use std::borrow::{Cow, ToOwned}; +use std::fmt::{self, Debug, Display, Formatter}; +use std::ops::Deref; + +/// Wrapper `Cow<'_, str>` for deserializing without allocation. +#[derive(Default)] +pub struct CowStr<'a>(Cow<'a, str>); + +impl<'a> CowStr<'a> { + /// Convert into `Cow<'a, str>`. + pub fn into_inner(self) -> Cow<'a, str> { + self.0 + } +} + +impl<'de> Deserialize<'de> for CowStr<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct Visitor; + + impl<'de> serde::de::Visitor<'de> for Visitor { + type Value = CowStr<'de>; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string") + } + + fn visit_borrowed_str(self, value: &'de str) -> Result + where + E: de::Error, + { + Ok(CowStr(Cow::Borrowed(value))) + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + Ok(CowStr(Cow::Owned(value.to_owned()))) + } + + fn visit_string(self, value: String) -> Result + where + E: de::Error, + { + Ok(CowStr(Cow::Owned(value))) + } + } + + deserializer.deserialize_str(Visitor) + } +} + +impl<'a> Serialize for CowStr<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.0) + } +} + +impl<'a> Debug for CowStr<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + <&str as Debug>::fmt(&&*self.0, f) + } +} + +impl<'a> Display for CowStr<'a> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + <&str as Display>::fmt(&&*self.0, f) + } +} + +impl<'a> Deref for CowStr<'a> { + type Target = str; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> AsRef for CowStr<'a> { + fn as_ref(&self) -> &str { + &self.0 + } +} + +impl<'a> AsRef<[u8]> for CowStr<'a> { + fn as_ref(&self) -> &[u8] { + self.0.as_bytes() + } +} + +impl<'a> From> for Cow<'a, str> { + fn from(value: CowStr<'a>) -> Self { + value.0 + } +} + +impl<'a> From> for CowStr<'a> { + fn from(value: Cow<'a, str>) -> Self { + CowStr(value) + } +} + +/// Serialize `Cow<'_, str>`. +pub fn serialize<'a, S>(value: &Cow<'a, str>, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_str(value) +} + +/// Deserialize `Cow<'_, str>`. +pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + CowStr::deserialize(deserializer).map(|value| value.into_inner()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn borrowed() { + struct Test(u32); + + impl<'de> Deserialize<'de> for Test { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = CowStr::deserialize(deserializer)?; + assert!(matches!(s.0, Cow::Borrowed(_))); + Ok(Test(s.parse().unwrap())) + } + } + + let v = serde_json::from_str::("\"2\"").unwrap(); + assert_eq!(v.0, 2); + } + + #[test] + fn owned() { + struct Test(u32); + + impl<'de> Deserialize<'de> for Test { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = CowStr::deserialize(deserializer)?; + assert!(matches!(s.0, Cow::Owned(_))); + Ok(Test(s.parse().unwrap())) + } + } + + let json_value = serde_json::from_str::("\"2\"").unwrap(); + let v = serde_json::from_value::(json_value).unwrap(); + assert_eq!(v.0, 2); + } +} diff --git a/proto/src/serializers/from_str.rs b/proto/src/serializers/from_str.rs new file mode 100644 index 00000000..26d545af --- /dev/null +++ b/proto/src/serializers/from_str.rs @@ -0,0 +1,31 @@ +//! Serialize and deserialize any `T` that implements [`FromStr`] +//! and [`Display`] from or into string. Note this can be used for +//! all primitive data types. + +use std::fmt::Display; +use std::str::FromStr; + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + +use crate::serializers::cow_str::CowStr; + +/// Deserialize string into T +pub fn deserialize<'de, D, T>(deserializer: D) -> Result +where + D: Deserializer<'de>, + T: FromStr, + ::Err: Display, +{ + CowStr::deserialize(deserializer)? + .parse::() + .map_err(serde::de::Error::custom) +} + +/// Serialize from T into string +pub fn serialize(value: &T, serializer: S) -> Result +where + S: Serializer, + T: Display, +{ + value.to_string().serialize(serializer) +} diff --git a/proto/src/serializers/option_any.rs b/proto/src/serializers/option_any.rs deleted file mode 100644 index f266dbb5..00000000 --- a/proto/src/serializers/option_any.rs +++ /dev/null @@ -1,103 +0,0 @@ -//! [`serde`] serializer for the optional [`Any`]. - -#[cfg(feature = "tonic")] -use pbjson_types::Any; -#[cfg(not(feature = "tonic"))] -use prost_types::Any; - -use serde::{Deserialize, Deserializer, Serialize, Serializer}; - -/// Deserialize `Option`. -pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> -where - D: Deserializer<'de>, -{ - #[derive(Deserialize)] - struct Def { - type_url: String, - #[serde(with = "celestia_tendermint_proto::serializers::bytes::base64string")] - value: Vec, - } - - let any = Option::::deserialize(deserializer)?.map(|def| Any { - type_url: def.type_url, - value: def.value.into(), - }); - - Ok(any) -} - -/// Serialize `Option`. -pub fn serialize(value: &Option, serializer: S) -> Result -where - S: Serializer, -{ - #[derive(Serialize)] - struct Def<'a> { - type_url: &'a str, - #[serde(with = "celestia_tendermint_proto::serializers::bytes::base64string")] - value: &'a [u8], - } - - match value { - Some(any) => { - let def = Def { - type_url: &any.type_url, - value: &any.value, - }; - - def.serialize(serializer) - } - None => serializer.serialize_none(), - } -} - -#[cfg(test)] -mod tests { - use super::*; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::wasm_bindgen_test as test; - - #[derive(Serialize, Deserialize)] - struct TxResponse { - #[serde(default, with = "super")] - tx: Option, - } - - #[test] - fn serialize() { - let msg = TxResponse { - tx: Some(Any { - type_url: "abc".to_string(), - value: vec![1, 2, 3].into(), - }), - }; - let json = serde_json::to_string(&msg).unwrap(); - assert_eq!(json, r#"{"tx":{"type_url":"abc","value":"AQID"}}"#); - } - - #[test] - fn serialize_none() { - let msg = TxResponse { tx: None }; - let json = serde_json::to_string(&msg).unwrap(); - assert_eq!(json, r#"{"tx":null}"#); - } - - #[test] - fn deserialize() { - let msg: TxResponse = - serde_json::from_str(r#"{"tx":{"type_url":"abc","value":"AQID"}}"#).unwrap(); - let tx = msg.tx.unwrap(); - assert_eq!(tx.type_url, "abc"); - assert_eq!(tx.value.as_ref(), [1, 2, 3]) - } - - #[test] - fn deserialize_none() { - let msg: TxResponse = serde_json::from_str(r#"{"tx":null}"#).unwrap(); - assert_eq!(msg.tx, None); - - let msg: TxResponse = serde_json::from_str(r#"{}"#).unwrap(); - assert_eq!(msg.tx, None); - } -} diff --git a/proto/src/serializers/option_protobuf_duration.rs b/proto/src/serializers/option_protobuf_duration.rs new file mode 100644 index 00000000..65e23fc8 --- /dev/null +++ b/proto/src/serializers/option_protobuf_duration.rs @@ -0,0 +1,40 @@ +//! [`serde`] serializer for optional [`Duration`]. + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use tendermint_proto::google::protobuf::Duration; + +#[derive(Serialize, Deserialize)] +struct Def { + seconds: i64, + nanos: i32, +} + +/// Deserialize [`Option`]. +pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + Ok( + Option::::deserialize(deserializer)?.map(|def| Duration { + seconds: def.seconds, + nanos: def.nanos, + }), + ) +} + +/// Serialize [`Option`]. +pub fn serialize(value: &Option, serializer: S) -> Result +where + S: Serializer, +{ + match value { + Some(value) => { + let def = Def { + seconds: value.seconds, + nanos: value.nanos, + }; + serializer.serialize_some(&def) + } + None => serializer.serialize_none(), + } +} diff --git a/proto/src/serializers/option_timestamp.rs b/proto/src/serializers/option_timestamp.rs index 7563ccd0..3c15bbd3 100644 --- a/proto/src/serializers/option_timestamp.rs +++ b/proto/src/serializers/option_timestamp.rs @@ -1,8 +1,8 @@ //! [`serde`] serializer for the optional [`Timestamp`]. -use celestia_tendermint_proto::google::protobuf::Timestamp; -use celestia_tendermint_proto::serializers::timestamp; use serde::{Deserialize, Deserializer, Serializer}; +use tendermint_proto::google::protobuf::Timestamp; +use tendermint_proto::serializers::timestamp; /// Deserialize `Option`. pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> diff --git a/proto/vendor/go-square/blob/v1/blob.proto b/proto/vendor/go-square/blob/v1/blob.proto new file mode 100644 index 00000000..df379252 --- /dev/null +++ b/proto/vendor/go-square/blob/v1/blob.proto @@ -0,0 +1,35 @@ +syntax = "proto3"; +package proto.blob.v1; + +option go_package = "github.com/celestiaorg/go-square/v2/proto/blob/v1"; + +// BlobProto is the protobuf representation of a blob (binary large object) +// to be published to the Celestia blockchain. The data of a Blob is published +// to a namespace and is encoded into shares based on the format specified by +// share_version. +message BlobProto { + bytes namespace_id = 1; + bytes data = 2; + uint32 share_version = 3; + uint32 namespace_version = 4; + // Signer is sdk.AccAddress that paid for this blob. This field is optional + // and can only be used when share_version is set to 1. + bytes signer = 5; +} + +// BlobTx wraps an encoded sdk.Tx with a second field to contain blobs of data. +// The raw bytes of the blobs are not signed over, instead we verify each blob +// using the relevant MsgPayForBlobs that is signed over in the encoded sdk.Tx. +message BlobTx { + bytes tx = 1; + repeated BlobProto blobs = 2; + string type_id = 3; +} + +// IndexWrapper adds index metadata to a transaction. This is used to track +// transactions that pay for blobs, and where the blobs start in the square. +message IndexWrapper { + bytes tx = 1; + repeated uint32 share_indexes = 2; + string type_id = 3; +} diff --git a/proto/vendor/tendermint-celestia-mods/abci/types.proto b/proto/vendor/tendermint-celestia-mods/abci/types.proto new file mode 100644 index 00000000..88552b6c --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/abci/types.proto @@ -0,0 +1,165 @@ +syntax = "proto3"; +package tendermint_celestia_mods.abci; + +import "tendermint/types/types.proto"; +import "google/protobuf/timestamp.proto"; +import "gogoproto/gogo.proto"; +import "google/protobuf/duration.proto"; + +import "tendermint-celestia-mods/types/types.proto"; +import "tendermint/abci/types.proto"; + +// This file is copied from http://github.com/tendermint/abci +// NOTE: When using custom types, mind the warnings. +// https://github.com/gogo/protobuf/blob/master/custom_types.md#warnings-and-issues + +//---------------------------------------- +// Request types + +message Request { + oneof value { + tendermint.abci.RequestEcho echo = 1; + tendermint.abci.RequestFlush flush = 2; + tendermint.abci.RequestInfo info = 3; + tendermint.abci.RequestSetOption set_option = 4; + tendermint.abci.RequestInitChain init_chain = 5; + tendermint.abci.RequestQuery query = 6; + tendermint.abci.RequestBeginBlock begin_block = 7; + tendermint.abci.RequestCheckTx check_tx = 8; + tendermint.abci.RequestDeliverTx deliver_tx = 9; + tendermint.abci.RequestEndBlock end_block = 10; + tendermint.abci.RequestCommit commit = 11; + tendermint.abci.RequestListSnapshots list_snapshots = 12; + RequestOfferSnapshot offer_snapshot = 13; + tendermint.abci.RequestLoadSnapshotChunk load_snapshot_chunk = 14; + tendermint.abci.RequestApplySnapshotChunk apply_snapshot_chunk = 15; + RequestPrepareProposal prepare_proposal = 16; + RequestProcessProposal process_proposal = 17; + } +} + +message TimeoutsInfo { + google.protobuf.Duration timeout_propose = 1 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; + google.protobuf.Duration timeout_commit = 2 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; +} + +// offers a snapshot to the application +message RequestOfferSnapshot { + tendermint.abci.Snapshot snapshot = 1; // snapshot offered by peers + bytes app_hash = 2; // light client-verified app hash for snapshot height + uint64 app_version = 3; // The application version at which the snapshot was taken +} + +message RequestPrepareProposal { + // BlockData is a slice of candidate transactions that may be included in a + // block. BlockData is sent to the application so that the application can + // filter and re-arrange the slice of candidate transactions. + tendermint_celestia_mods.types.Data block_data = 1; + // BlockDataSize is the maximum size (in bytes) that BlockData should be. + int64 block_data_size = 2; + // chain_id is a unique identifier for the blockchain network this proposal + // belongs to (e.g. mocha-1). + string chain_id = 3; + // height is the height of the proposal block + int64 height = 4; + // time is the time that will end up in the header. This is the voting power + // weighted median of the last commit. + google.protobuf.Timestamp time = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; +} + +message RequestProcessProposal { + tendermint.types.Header header = 1 [(gogoproto.nullable) = false]; + tendermint_celestia_mods.types.Data block_data = 2; +} + +//---------------------------------------- +// Response types + +message Response { + oneof value { + tendermint.abci.ResponseException exception = 1; + tendermint.abci.ResponseEcho echo = 2; + tendermint.abci.ResponseFlush flush = 3; + ResponseInfo info = 4; + tendermint.abci.ResponseSetOption set_option = 5; + ResponseInitChain init_chain = 6; + tendermint.abci.ResponseQuery query = 7; + tendermint.abci.ResponseBeginBlock begin_block = 8; + tendermint.abci.ResponseCheckTx check_tx = 9; + tendermint.abci.ResponseDeliverTx deliver_tx = 10; + ResponseEndBlock end_block = 11; + tendermint.abci.ResponseCommit commit = 12; + tendermint.abci.ResponseListSnapshots list_snapshots = 13; + tendermint.abci.ResponseOfferSnapshot offer_snapshot = 14; + tendermint.abci.ResponseLoadSnapshotChunk load_snapshot_chunk = 15; + tendermint.abci.ResponseApplySnapshotChunk apply_snapshot_chunk = 16; + ResponsePrepareProposal prepare_proposal = 17; + ResponseProcessProposal process_proposal = 18; + } +} + +message ResponseInitChain { + tendermint.abci.ConsensusParams consensus_params = 1; + repeated tendermint.abci.ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; + bytes app_hash = 3; + TimeoutsInfo timeouts = 4 [(gogoproto.nullable) = false]; +} + +message ResponseInfo { + string data = 1; + + string version = 2; + uint64 app_version = 3; + + int64 last_block_height = 4; + bytes last_block_app_hash = 5; + + TimeoutsInfo timeouts = 6 [(gogoproto.nullable) = false]; +} + +message ResponseEndBlock { + repeated tendermint.abci.ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false]; + tendermint.abci.ConsensusParams consensus_param_updates = 2; + repeated tendermint.abci.Event events = 3 + [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; + TimeoutsInfo timeouts = 4 [(gogoproto.nullable) = false]; +} + +message ResponsePrepareProposal { + tendermint_celestia_mods.types.Data block_data = 1; +} + +message ResponseProcessProposal { + Result result = 1; + repeated bytes evidence = 2; + + enum Result { + UNKNOWN = 0; // Unknown result, invalidate + ACCEPT = 1; // proposal verified, vote on the proposal + REJECT = 2; // proposal invalidated + } +} + + +//---------------------------------------- +// Service Definition + +service ABCIApplication { + rpc Echo(tendermint.abci.RequestEcho) returns (tendermint.abci.ResponseEcho); + rpc Flush(tendermint.abci.RequestFlush) returns (tendermint.abci.ResponseFlush); + rpc Info(tendermint.abci.RequestInfo) returns (ResponseInfo); + rpc SetOption(tendermint.abci.RequestSetOption) returns (tendermint.abci.ResponseSetOption); + rpc DeliverTx(tendermint.abci.RequestDeliverTx) returns (tendermint.abci.ResponseDeliverTx); + rpc CheckTx(tendermint.abci.RequestCheckTx) returns (tendermint.abci.ResponseCheckTx); + rpc Query(tendermint.abci.RequestQuery) returns (tendermint.abci.ResponseQuery); + rpc Commit(tendermint.abci.RequestCommit) returns (tendermint.abci.ResponseCommit); + rpc InitChain(tendermint.abci.RequestInitChain) returns (ResponseInitChain); + rpc BeginBlock(tendermint.abci.RequestBeginBlock) returns (tendermint.abci.ResponseBeginBlock); + rpc EndBlock(tendermint.abci.RequestEndBlock) returns (ResponseEndBlock); + rpc ListSnapshots(tendermint.abci.RequestListSnapshots) returns (tendermint.abci.ResponseListSnapshots); + rpc OfferSnapshot(RequestOfferSnapshot) returns (tendermint.abci.ResponseOfferSnapshot); + rpc LoadSnapshotChunk(tendermint.abci.RequestLoadSnapshotChunk) returns (tendermint.abci.ResponseLoadSnapshotChunk); + rpc ApplySnapshotChunk(tendermint.abci.RequestApplySnapshotChunk) returns (tendermint.abci.ResponseApplySnapshotChunk); + rpc PrepareProposal(RequestPrepareProposal) returns (ResponsePrepareProposal); + rpc ProcessProposal(RequestProcessProposal) returns (ResponseProcessProposal); +} diff --git a/proto/vendor/tendermint-celestia-mods/blockchain/types.proto b/proto/vendor/tendermint-celestia-mods/blockchain/types.proto new file mode 100644 index 00000000..698634f9 --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/blockchain/types.proto @@ -0,0 +1,21 @@ +syntax = "proto3"; +package tendermint_celestia_mods.blockchain; + +import "tendermint/types/block.proto"; +import "tendermint/blockchain/types.proto"; +import "tendermint-celestia-mods/types/block.proto"; + +// BlockResponse returns block to the requested +message BlockResponse { + tendermint_celestia_mods.types.Block block = 1; +} + +message Message { + oneof sum { + tendermint.blockchain.BlockRequest block_request = 1; + tendermint.blockchain.NoBlockResponse no_block_response = 2; + BlockResponse block_response = 3; + tendermint.blockchain.StatusRequest status_request = 4; + tendermint.blockchain.StatusResponse status_response = 5; + } +} diff --git a/proto/vendor/tendermint-celestia-mods/mempool/types.proto b/proto/vendor/tendermint-celestia-mods/mempool/types.proto new file mode 100644 index 00000000..6d8a8cfe --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/mempool/types.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package tendermint_celestia_mods.mempool; + +import "tendermint/mempool/types.proto"; + +message SeenTx { + bytes tx_key = 1; +} + +message WantTx { + bytes tx_key = 1; +} + +message Message { + oneof sum { + tendermint.mempool.Txs txs = 1; + SeenTx seen_tx = 2; + WantTx want_tx = 3; + } +} diff --git a/proto/vendor/tendermint-celestia-mods/state/types.proto b/proto/vendor/tendermint-celestia-mods/state/types.proto new file mode 100644 index 00000000..cc447996 --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/state/types.proto @@ -0,0 +1,66 @@ +syntax = "proto3"; +package tendermint_celestia_mods.state; + +import "gogoproto/gogo.proto"; +import "tendermint/abci/types.proto"; +import "tendermint/types/types.proto"; +import "tendermint/types/validator.proto"; +import "tendermint/types/params.proto"; +import "google/protobuf/timestamp.proto"; + +import "tendermint/state/types.proto"; +import "tendermint-celestia-mods/abci/types.proto"; + +// ABCIResponses retains the responses +// of the various ABCI calls during block processing. +// It is persisted to disk for each height before calling Commit. +message ABCIResponses { + repeated tendermint.abci.ResponseDeliverTx deliver_txs = 1; + tendermint_celestia_mods.abci.ResponseEndBlock end_block = 2; + tendermint.abci.ResponseBeginBlock begin_block = 3; +} + +message ABCIResponsesInfo { + ABCIResponses abci_responses = 1; + int64 height = 2; +} + +message State { + tendermint.state.Version version = 1 [(gogoproto.nullable) = false]; + + // immutable + string chain_id = 2 [(gogoproto.customname) = "ChainID"]; + int64 initial_height = 14; + + // LastBlockHeight=0 at genesis (ie. block(H=0) does not exist) + int64 last_block_height = 3; + tendermint.types.BlockID last_block_id = 4 + [(gogoproto.nullable) = false, (gogoproto.customname) = "LastBlockID"]; + google.protobuf.Timestamp last_block_time = 5 + [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + + // LastValidators is used to validate block.LastCommit. + // Validators are persisted to the database separately every time they change, + // so we can query for historical validator sets. + // Note that if s.LastBlockHeight causes a valset change, + // we set s.LastHeightValidatorsChanged = s.LastBlockHeight + 1 + 1 + // Extra +1 due to nextValSet delay. + tendermint.types.ValidatorSet next_validators = 6; + tendermint.types.ValidatorSet validators = 7; + tendermint.types.ValidatorSet last_validators = 8; + int64 last_height_validators_changed = 9; + + // Consensus parameters used for validating blocks. + // Changes returned by EndBlock and updated after Commit. + tendermint.types.ConsensusParams consensus_params = 10 [(gogoproto.nullable) = false]; + int64 last_height_consensus_params_changed = 11; + + // Merkle root of the results from executing prev block + bytes last_results_hash = 12; + + // the latest AppHash we've received from calling abci.Commit() + bytes app_hash = 13; + + // timeouts to be used for the next block height + tendermint_celestia_mods.abci.TimeoutsInfo timeouts = 15 [(gogoproto.nullable) = false]; +} diff --git a/proto/vendor/tendermint-celestia-mods/store/types.proto b/proto/vendor/tendermint-celestia-mods/store/types.proto new file mode 100644 index 00000000..e90925fe --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/store/types.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package tendermint_celestia_mods.store; + +// TxInfo describes the location of a tx inside a committed block +// as well as the result of executing the transaction and the error log output. +message TxInfo { + int64 height = 1; + uint32 index = 2; + // The response code of executing the tx. 0 means + // successfully executed, all others are error codes. + uint32 code = 3; + // The error log output generated if the transaction execution fails. + string error = 4; +} diff --git a/proto/vendor/tendermint-celestia-mods/types/block.proto b/proto/vendor/tendermint-celestia-mods/types/block.proto new file mode 100644 index 00000000..9d830fe0 --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/types/block.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package tendermint_celestia_mods.types; + +import "gogoproto/gogo.proto"; +import "tendermint/types/types.proto"; +import "tendermint/types/evidence.proto"; +import "tendermint-celestia-mods/types/types.proto"; + +message Block { + tendermint.types.Header header = 1 [(gogoproto.nullable) = false]; + Data data = 2 [(gogoproto.nullable) = false]; + tendermint.types.EvidenceList evidence = 3 [(gogoproto.nullable) = false]; + tendermint.types.Commit last_commit = 4; +} diff --git a/proto/vendor/tendermint-celestia-mods/types/types.proto b/proto/vendor/tendermint-celestia-mods/types/types.proto new file mode 100644 index 00000000..092f1009 --- /dev/null +++ b/proto/vendor/tendermint-celestia-mods/types/types.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; +package tendermint_celestia_mods.types; + +// Data contains all the information needed for a consensus full node to +// reconstruct an extended data square. +message Data { + // Txs that will be applied to state in block.Height + 1 because deferred execution. + // This means that the block.AppHash of this block does not include these txs. + // NOTE: not all txs here are valid. We're just agreeing on the order first. + repeated bytes txs = 1; + + reserved 2, 3, 4; + // field number 2 is reserved for intermediate state roots + // field number 3 is reserved for evidence + // field number 4 is reserved for blobs + + // SquareSize is the number of rows or columns in the original data square. + uint64 square_size = 5; + + // Hash is the root of a binary Merkle tree where the leaves of the tree are + // the row and column roots of an extended data square. Hash is often referred + // to as the "data root". + bytes hash = 6; +} diff --git a/proto/vendor/tendermint/abci/types.proto b/proto/vendor/tendermint/abci/types.proto index 2adc2ba7..44f86112 100644 --- a/proto/vendor/tendermint/abci/types.proto +++ b/proto/vendor/tendermint/abci/types.proto @@ -11,7 +11,6 @@ import "tendermint/crypto/keys.proto"; import "tendermint/types/params.proto"; import "google/protobuf/timestamp.proto"; import "gogoproto/gogo.proto"; -import "google/protobuf/duration.proto"; // This file is copied from http://github.com/tendermint/abci // NOTE: When using custom types, mind the warnings. @@ -37,8 +36,6 @@ message Request { RequestOfferSnapshot offer_snapshot = 13; RequestLoadSnapshotChunk load_snapshot_chunk = 14; RequestApplySnapshotChunk apply_snapshot_chunk = 15; - RequestPrepareProposal prepare_proposal = 16; - RequestProcessProposal process_proposal = 17; } } @@ -48,11 +45,6 @@ message RequestEcho { message RequestFlush {} -message TimeoutsInfo { - google.protobuf.Duration timeout_propose = 1 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; - google.protobuf.Duration timeout_commit = 2 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true]; -} - message RequestInfo { string version = 1; uint64 block_version = 2; @@ -114,9 +106,8 @@ message RequestListSnapshots {} // offers a snapshot to the application message RequestOfferSnapshot { - Snapshot snapshot = 1; // snapshot offered by peers - bytes app_hash = 2; // light client-verified app hash for snapshot height - uint64 app_version = 3; // The application version at which the snapshot was taken + Snapshot snapshot = 1; // snapshot offered by peers + bytes app_hash = 2; // light client-verified app hash for snapshot height } // loads a snapshot chunk @@ -133,28 +124,6 @@ message RequestApplySnapshotChunk { string sender = 3; } -message RequestPrepareProposal { - // BlockData is a slice of candidate transactions that may be included in a - // block. BlockData is sent to the application so that the application can - // filter and re-arrange the slice of candidate transactions. - tendermint.types.Data block_data = 1; - // BlockDataSize is the maximum size (in bytes) that BlockData should be. - int64 block_data_size = 2; - // chain_id is a unique identifier for the blockchain network this proposal - // belongs to (e.g. mocha-1). - string chain_id = 3; - // height is the height of the proposal block - int64 height = 4; - // time is the time that will end up in the header. This is the voting power - // weighted median of the last commit. - google.protobuf.Timestamp time = 5 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; -} - -message RequestProcessProposal { - tendermint.types.Header header = 1 [(gogoproto.nullable) = false]; - tendermint.types.Data block_data = 2; -} - //---------------------------------------- // Response types @@ -176,8 +145,6 @@ message Response { ResponseOfferSnapshot offer_snapshot = 14; ResponseLoadSnapshotChunk load_snapshot_chunk = 15; ResponseApplySnapshotChunk apply_snapshot_chunk = 16; - ResponsePrepareProposal prepare_proposal = 17; - ResponseProcessProposal process_proposal = 18; } } @@ -200,8 +167,6 @@ message ResponseInfo { int64 last_block_height = 4; bytes last_block_app_hash = 5; - - TimeoutsInfo timeouts = 6 [(gogoproto.nullable) = false]; } // nondeterministic @@ -216,7 +181,6 @@ message ResponseInitChain { ConsensusParams consensus_params = 1; repeated ValidatorUpdate validators = 2 [(gogoproto.nullable) = false]; bytes app_hash = 3; - TimeoutsInfo timeouts = 4 [(gogoproto.nullable) = false]; } message ResponseQuery { @@ -274,7 +238,6 @@ message ResponseEndBlock { ConsensusParams consensus_param_updates = 2; repeated Event events = 3 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; - TimeoutsInfo timeouts = 4 [(gogoproto.nullable) = false]; } message ResponseCommit { @@ -319,21 +282,6 @@ message ResponseApplySnapshotChunk { } } -message ResponsePrepareProposal { - tendermint.types.Data block_data = 1; -} - -message ResponseProcessProposal { - Result result = 1; - repeated bytes evidence = 2; - - enum Result { - UNKNOWN = 0; // Unknown result, invalidate - ACCEPT = 1; // proposal verified, vote on the proposal - REJECT = 2; // proposal invalidated - } -} - //---------------------------------------- // Misc. @@ -458,8 +406,8 @@ service ABCIApplication { rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock); rpc ListSnapshots(RequestListSnapshots) returns (ResponseListSnapshots); rpc OfferSnapshot(RequestOfferSnapshot) returns (ResponseOfferSnapshot); - rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) returns (ResponseLoadSnapshotChunk); - rpc ApplySnapshotChunk(RequestApplySnapshotChunk) returns (ResponseApplySnapshotChunk); - rpc PrepareProposal(RequestPrepareProposal) returns (ResponsePrepareProposal); - rpc ProcessProposal(RequestProcessProposal) returns (ResponseProcessProposal); + rpc LoadSnapshotChunk(RequestLoadSnapshotChunk) + returns (ResponseLoadSnapshotChunk); + rpc ApplySnapshotChunk(RequestApplySnapshotChunk) + returns (ResponseApplySnapshotChunk); } diff --git a/proto/vendor/tendermint/mempool/types.proto b/proto/vendor/tendermint/mempool/types.proto index 75602411..b55d9717 100644 --- a/proto/vendor/tendermint/mempool/types.proto +++ b/proto/vendor/tendermint/mempool/types.proto @@ -7,18 +7,8 @@ message Txs { repeated bytes txs = 1; } -message SeenTx { - bytes tx_key = 1; -} - -message WantTx { - bytes tx_key = 1; -} - message Message { oneof sum { - Txs txs = 1; - SeenTx seen_tx = 2; - WantTx want_tx = 3; + Txs txs = 1; } } diff --git a/proto/vendor/tendermint/state/types.proto b/proto/vendor/tendermint/state/types.proto index 9796a8fc..f3fdc0ef 100644 --- a/proto/vendor/tendermint/state/types.proto +++ b/proto/vendor/tendermint/state/types.proto @@ -77,7 +77,4 @@ message State { // the latest AppHash we've received from calling abci.Commit() bytes app_hash = 13; - - // timeouts to be used for the next block height - tendermint.abci.TimeoutsInfo timeouts = 15 [(gogoproto.nullable) = false]; } diff --git a/proto/vendor/tendermint/store/types.proto b/proto/vendor/tendermint/store/types.proto index 64a32d1f..af2f97ad 100644 --- a/proto/vendor/tendermint/store/types.proto +++ b/proto/vendor/tendermint/store/types.proto @@ -7,15 +7,3 @@ message BlockStoreState { int64 base = 1; int64 height = 2; } - -// TxInfo describes the location of a tx inside a committed block -// as well as the result of executing the transaction and the error log output. -message TxInfo { - int64 height = 1; - uint32 index = 2; - // The response code of executing the tx. 0 means - // successfully executed, all others are error codes. - uint32 code = 3; - // The error log output generated if the transaction execution fails. - string error = 4; -} diff --git a/proto/vendor/tendermint/types/types.proto b/proto/vendor/tendermint/types/types.proto index d3ccf4a2..3ce16945 100644 --- a/proto/vendor/tendermint/types/types.proto +++ b/proto/vendor/tendermint/types/types.proto @@ -81,37 +81,12 @@ message Header { bytes proposer_address = 14; // original proposer of the block } -// Data contains all the information needed for a consensus full node to -// reconstruct an extended data square. +// Data contains the set of transactions included in the block message Data { - // Txs that will be applied to state in block.Height + 1 because deferred execution. - // This means that the block.AppHash of this block does not include these txs. - // NOTE: not all txs here are valid. We're just agreeing on the order first. + // Txs that will be applied by state @ block.Height+1. + // NOTE: not all txs here are valid. We're just agreeing on the order first. + // This means that block.AppHash does not include these txs. repeated bytes txs = 1; - - reserved 2, 3, 4; - // field number 2 is reserved for intermediate state roots - // field number 3 is reserved for evidence - // field number 4 is reserved for blobs - - // SquareSize is the number of rows or columns in the original data square. - uint64 square_size = 5; - - // Hash is the root of a binary Merkle tree where the leaves of the tree are - // the row and column roots of an extended data square. Hash is often referred - // to as the "data root". - bytes hash = 6; -} - -// Blob (named after binary large object) is a chunk of data submitted by a user -// to be published to the Celestia blockchain. The data of a Blob is published -// to a namespace and is encoded into shares based on the format specified by -// share_version. -message Blob { - bytes namespace_id = 1; - bytes data = 2; - uint32 share_version = 3; - uint32 namespace_version = 4; } // Vote represents a prevote, precommit, or commit vote from validators for @@ -174,78 +149,9 @@ message BlockMeta { int64 num_txs = 4; } -// TxProof represents a Merkle proof of the presence of a transaction in the -// Merkle tree. -// -// Note: TxProof is not used in celestia-core because of modifications to the -// data root. In a normal Cosmos chain, the data root is the root of a Merkle -// tree of transactions in the block. However, in Celestia the data root is the -// root of the row and column roots in the extended data square. See -// https://github.com/celestiaorg/celestia-app/blob/852a229f11f0f269021b36f7621609f432bb858b/pkg/da/data_availability_header.go -// for more details. Therefore, TxProof isn't sufficient to prove the existence -// of a transaction in a Celestia block and ShareProof was defined instead. See -// ShareProof for more details. +// TxProof represents a Merkle proof of the presence of a transaction in the Merkle tree. message TxProof { bytes root_hash = 1; bytes data = 2; tendermint.crypto.Proof proof = 3; } - -// IndexWrapper adds index metadata to a transaction. This is used to track -// transactions that pay for blobs, and where the blobs start in the square. -message IndexWrapper { - bytes tx = 1; - repeated uint32 share_indexes = 2; - string type_id = 3; -} - -// BlobTx wraps an encoded sdk.Tx with a second field to contain blobs of data. -// The raw bytes of the blobs are not signed over, instead we verify each blob -// using the relevant MsgPayForBlobs that is signed over in the encoded sdk.Tx. -message BlobTx { - bytes tx = 1; - repeated Blob blobs = 2; - string type_id = 3; -} - -// ShareProof is an NMT proof that a set of shares exist in a set of rows and a -// Merkle proof that those rows exist in a Merkle tree with a given data root. -message ShareProof { - repeated bytes data = 1; - repeated NMTProof share_proofs = 2; - bytes namespace_id = 3; - RowProof row_proof = 4; - uint32 namespace_version = 5; -} - -// RowProof is a Merkle proof that a set of rows exist in a Merkle tree with a -// given data root. -message RowProof { - repeated bytes row_roots = 1; - repeated tendermint.crypto.Proof proofs = 2; - bytes root = 3; - uint32 start_row = 4; - uint32 end_row = 5; -} - -// NMTProof is a proof of a namespace.ID in an NMT. -// In case this proof proves the absence of a namespace.ID -// in a tree it also contains the leaf hashes of the range -// where that namespace would be. -message NMTProof { - // Start index of this proof. - int32 start = 1; - // End index of this proof. - int32 end = 2; - // Nodes that together with the corresponding leaf values can be used to - // recompute the root and verify this proof. Nodes should consist of the max - // and min namespaces along with the actual hash, resulting in each being 48 - // bytes each - repeated bytes nodes = 3; - // leafHash are nil if the namespace is present in the NMT. In case the - // namespace to be proved is in the min/max range of the tree but absent, this - // will contain the leaf hash necessary to verify the proof of absence. Leaf - // hashes should consist of the namespace along with the actual hash, - // resulting 40 bytes total. - bytes leaf_hash = 4; -} diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 4b14163a..609a8473 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -19,9 +19,7 @@ categories = [ ] [dependencies] -celestia-tendermint-proto.workspace = true celestia-types.workspace = true -celestia-tendermint.workspace = true prost.workspace = true async-trait = "0.1.80" diff --git a/tools/update-proto-vendor.sh b/tools/update-proto-vendor.sh index 5b850524..59547ce0 100755 --- a/tools/update-proto-vendor.sh +++ b/tools/update-proto-vendor.sh @@ -24,13 +24,14 @@ mkdir -p ../target/proto-vendor-src extract_urls ../target/proto-vendor-src \ https://github.com/celestiaorg/celestia-app/archive/refs/tags/v2.3.0.tar.gz \ - https://github.com/celestiaorg/celestia-core/archive/refs/heads/v0.34.x-celestia.tar.gz \ https://github.com/celestiaorg/celestia-node/archive/refs/heads/main.tar.gz \ https://github.com/celestiaorg/cosmos-sdk/archive/refs/heads/release/v0.46.x-celestia.tar.gz \ + https://github.com/cometbft/cometbft/archive/refs/tags/v0.34.35.tar.gz \ https://github.com/celestiaorg/nmt/archive/refs/heads/main.tar.gz \ https://github.com/cosmos/cosmos-proto/archive/refs/tags/v1.0.0-alpha7.tar.gz \ https://github.com/cosmos/gogoproto/archive/refs/tags/v1.4.11.tar.gz \ https://github.com/celestiaorg/go-header/archive/refs/heads/main.tar.gz \ + https://github.com/celestiaorg/go-square/archive/refs/heads/main.tar.gz \ https://github.com/googleapis/googleapis/archive/refs/heads/master.tar.gz \ mkdir -p vendor @@ -42,6 +43,9 @@ rm -rf vendor/go-header mkdir -p vendor/go-header/p2p cp -r ../target/proto-vendor-src/go-header-main/p2p/pb vendor/go-header/p2p +rm -rf vendor/go-square +cp -r ../target/proto-vendor-src/go-square-main/proto vendor/go-square + rm -rf vendor/cosmos mkdir -p vendor/cosmos cp -r ../target/proto-vendor-src/cosmos-sdk-release-v0.46.x-celestia/proto/cosmos/{auth,base,staking,crypto,tx} vendor/cosmos @@ -74,7 +78,7 @@ find "$shwap_dir" -name pb -type d -print0 | while read -r -d '' pb_dir; do done rm -rf vendor/tendermint -cp -r ../target/proto-vendor-src/celestia-core-0.34.x-celestia/proto/tendermint vendor +cp -r ../target/proto-vendor-src/cometbft-0.34.35/proto/tendermint vendor rm -rf vendor/nmt mkdir -p vendor/nmt diff --git a/types/Cargo.toml b/types/Cargo.toml index c2363c49..c703dcc2 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -16,11 +16,10 @@ categories = ["encoding", "cryptography::cryptocurrencies"] [dependencies] blockstore.workspace = true celestia-proto.workspace = true -celestia-tendermint = { workspace = true, features = ["std", "rust-crypto", "secp256k1"] } -celestia-tendermint-proto.workspace = true nmt-rs.workspace = true prost.workspace = true -prost-types.workspace = true +tendermint = { workspace = true, features = ["std", "rust-crypto", "secp256k1"] } +tendermint-proto.workspace = true base64 = "0.22.1" bech32 = "0.11.0" @@ -34,16 +33,12 @@ leopard-codec = "0.1.0" libp2p-identity = { version = "0.2.9", optional = true } multiaddr = { version = "0.18.1", optional = true } multihash = "0.19.1" -pbjson-types = { version = "0.7.0", optional = true } rand = { version = "0.8.5", optional = true } ruint = { version = "1.12.3", features = ["serde"] } serde = { version = "1.0.203", features = ["derive"] } serde_repr = { version = "0.1.19", optional = true } sha2 = "0.10.6" thiserror = "1.0.61" - -# `time` is a dependency of a dependency but we need to specify it -# for fixing rust-lang/rust#125319. time = { version = "0.3.36", default-features = false } [dev-dependencies] @@ -62,8 +57,7 @@ wasm-bindgen-test = "0.3.42" default = ["p2p"] p2p = ["dep:libp2p-identity", "dep:multiaddr", "dep:serde_repr"] test-utils = ["dep:ed25519-consensus", "dep:rand"] -wasm-bindgen = ["celestia-tendermint/wasm-bindgen"] -tonic = ["dep:pbjson-types", "celestia-proto/tonic"] +wasm-bindgen = ["time/wasm-bindgen"] [package.metadata.docs.rs] features = ["p2p", "test-utils"] @@ -71,4 +65,3 @@ rustdoc-args = ["--cfg", "docsrs"] [package.metadata.cargo-udeps.ignore] development = ["indoc"] -normal = ["prost-types"] # unused if tonic flag is enabled diff --git a/types/src/blob.rs b/types/src/blob.rs index e0a63cf2..697b3bed 100644 --- a/types/src/blob.rs +++ b/types/src/blob.rs @@ -15,8 +15,8 @@ use crate::{bail_validation, Error, Result, Share}; pub use self::commitment::Commitment; pub use self::msg_pay_for_blobs::MsgPayForBlobs; pub use celestia_proto::celestia::blob::v1::MsgPayForBlobs as RawMsgPayForBlobs; -pub use celestia_tendermint_proto::v0_34::types::Blob as RawBlob; -pub use celestia_tendermint_proto::v0_34::types::BlobTx as RawBlobTx; +pub use celestia_proto::proto::blob::v1::BlobProto as RawBlob; +pub use celestia_proto::proto::blob::v1::BlobTx as RawBlobTx; /// Arbitrary data that can be stored in the network within certain [`Namespace`]. // NOTE: We don't use the `serde(try_from)` pattern for this type @@ -27,7 +27,7 @@ pub struct Blob { /// A [`Namespace`] the [`Blob`] belongs to. pub namespace: Namespace, /// Data stored within the [`Blob`]. - #[serde(with = "celestia_tendermint_proto::serializers::bytes::base64string")] + #[serde(with = "tendermint_proto::serializers::bytes::base64string")] pub data: Vec, /// Version indicating the format in which [`Share`]s should be created from this [`Blob`]. /// @@ -316,6 +316,7 @@ impl From for RawBlob { namespace_version: value.namespace.version() as u32, data: value.data, share_version: value.share_version as u32, + signer: Vec::new(), } } } diff --git a/types/src/blob/commitment.rs b/types/src/blob/commitment.rs index a8242f51..0f7effb3 100644 --- a/types/src/blob/commitment.rs +++ b/types/src/blob/commitment.rs @@ -3,11 +3,11 @@ use std::num::NonZeroU64; use base64::prelude::*; use bytes::{Buf, BufMut, BytesMut}; -use celestia_tendermint::crypto::sha256::HASH_SIZE; -use celestia_tendermint::{crypto, merkle}; -use celestia_tendermint_proto::serializers::cow_str::CowStr; +use celestia_proto::serializers::cow_str::CowStr; use nmt_rs::NamespaceMerkleHasher; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use tendermint::crypto::sha256::HASH_SIZE; +use tendermint::{crypto, merkle}; use crate::consts::appconsts; use crate::nmt::{Namespace, NamespacedHashExt, NamespacedSha2Hasher, Nmt, RawNamespacedHash}; @@ -46,7 +46,7 @@ use crate::{InfoByte, Share}; /// [`Blob`]: crate::Blob /// [`Share`]: crate::share::Share /// [`MsgPayForBlobs`]: celestia_proto::celestia::blob::v1::MsgPayForBlobs -/// [`merkle hash`]: celestia_tendermint::merkle::simple_hash_from_byte_vectors +/// [`merkle hash`]: tendermint::merkle::simple_hash_from_byte_vectors /// [`Nmt`]: crate::nmt::Nmt /// [`ExtendedDataSquare`]: crate::ExtendedDataSquare /// [`share commitment rules`]: https://github.com/celestiaorg/celestia-app/blob/main/specs/src/specs/data_square_layout.md#blob-share-commitment-rules diff --git a/types/src/blob/msg_pay_for_blobs.rs b/types/src/blob/msg_pay_for_blobs.rs index 2fe76801..d333cf70 100644 --- a/types/src/blob/msg_pay_for_blobs.rs +++ b/types/src/blob/msg_pay_for_blobs.rs @@ -1,7 +1,9 @@ -use serde::{Deserialize, Serialize}; - use celestia_proto::celestia::blob::v1::MsgPayForBlobs as RawMsgPayForBlobs; -use celestia_tendermint_proto::Protobuf; +use celestia_proto::cosmos::tx::v1beta1::TxBody as RawTxBody; +use prost::Name; +use serde::{Deserialize, Serialize}; +use tendermint_proto::google::protobuf::Any; +use tendermint_proto::Protobuf; use crate::blob::{Blob, Commitment}; use crate::nmt::Namespace; @@ -54,32 +56,16 @@ impl MsgPayForBlobs { } } -#[cfg(feature = "tonic")] -mod tx_body_conversion { - use super::{MsgPayForBlobs, RawMsgPayForBlobs}; - - use std::convert::Infallible; - - use pbjson_types::Any; - use prost::Name; - - use celestia_proto::cosmos::tx::v1beta1::TxBody as RawTxBody; - use celestia_tendermint_proto::Protobuf; - - impl From for RawTxBody { - fn from(msg: MsgPayForBlobs) -> Self { - let msg_pay_for_blobs_value: Result<_, Infallible> = msg.encode_vec(); - let msg_pay_for_blobs_as_any = Any { - type_url: RawMsgPayForBlobs::type_url(), - value: msg_pay_for_blobs_value - .expect("Result to be Infallible") - .into(), - }; - - RawTxBody { - messages: vec![msg_pay_for_blobs_as_any], - ..RawTxBody::default() - } +impl From for RawTxBody { + fn from(msg: MsgPayForBlobs) -> Self { + let msg_pay_for_blobs_as_any = Any { + type_url: RawMsgPayForBlobs::type_url(), + value: msg.encode_vec(), + }; + + RawTxBody { + messages: vec![msg_pay_for_blobs_as_any], + ..RawTxBody::default() } } } diff --git a/types/src/block.rs b/types/src/block.rs index da1df2ad..2e06cf85 100644 --- a/types/src/block.rs +++ b/types/src/block.rs @@ -1,15 +1,129 @@ -use celestia_tendermint::block::{Commit, CommitSig, Header, Id}; -use celestia_tendermint::signature::SIGNATURE_LENGTH; -use celestia_tendermint::vote; -use celestia_tendermint::{chain, Hash, Vote}; +//! Blocks within the chains of a Tendermint network + +use celestia_proto::tendermint_celestia_mods::types::Block as RawBlock; +use serde::{Deserialize, Serialize}; +use tendermint::block::{Commit, CommitSig, Header, Id}; +use tendermint::signature::SIGNATURE_LENGTH; +use tendermint::{chain, evidence, vote, Vote}; +use tendermint_proto::Protobuf; use crate::consts::{genesis::MAX_CHAIN_ID_LEN, version}; +use crate::hash::Hash; use crate::{bail_validation, Error, Result, ValidateBasic, ValidationError}; +mod data; + +pub use data::Data; + pub(crate) const GENESIS_HEIGHT: u64 = 1; /// The height of the block in Celestia network. -pub type Height = celestia_tendermint::block::Height; +pub type Height = tendermint::block::Height; + +/// Blocks consist of a header, transactions, votes (the commit), and a list of +/// evidence of malfeasance (i.e. signing conflicting votes). +/// +/// This is a modified version of [`tendermint::block::Block`] which contains +/// [modifications](data-mod) that Celestia introduced. +/// +/// [data-mod]: https://github.com/celestiaorg/celestia-core/blob/a1268f7ae3e688144a613c8a439dd31818aae07d/proto/tendermint/types/types.proto#L84-L104 +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(try_from = "RawBlock", into = "RawBlock")] +pub struct Block { + /// Block header + pub header: Header, + + /// Transaction data + pub data: Data, + + /// Evidence of malfeasance + pub evidence: evidence::List, + + /// Last commit, should be `None` for the initial block. + pub last_commit: Option, +} + +impl Block { + /// Builds a new [`Block`], based on the given [`Header`], [`Data`], evidence, and last commit. + pub fn new( + header: Header, + data: Data, + evidence: evidence::List, + last_commit: Option, + ) -> Self { + Block { + header, + data, + evidence, + last_commit, + } + } + + /// Get header + pub fn header(&self) -> &Header { + &self.header + } + + /// Get data + pub fn data(&self) -> &Data { + &self.data + } + + /// Get evidence + pub fn evidence(&self) -> &evidence::List { + &self.evidence + } + + /// Get last commit + pub fn last_commit(&self) -> &Option { + &self.last_commit + } +} + +impl Protobuf for Block {} + +impl TryFrom for Block { + type Error = Error; + + fn try_from(value: RawBlock) -> Result { + let header: Header = value + .header + .ok_or_else(tendermint::Error::missing_header)? + .try_into()?; + + // If last_commit is the default Commit, it is considered nil by Go. + let last_commit = value + .last_commit + .map(TryInto::try_into) + .transpose()? + .filter(|c| c != &Commit::default()); + + Ok(Block::new( + header, + value + .data + .ok_or_else(tendermint::Error::missing_data)? + .try_into()?, + value + .evidence + .map(TryInto::try_into) + .transpose()? + .unwrap_or_default(), + last_commit, + )) + } +} + +impl From for RawBlock { + fn from(value: Block) -> Self { + RawBlock { + header: Some(value.header.into()), + data: Some(value.data.into()), + evidence: Some(value.evidence.into()), + last_commit: value.last_commit.map(Into::into), + } + } +} impl ValidateBasic for Header { fn validate_basic(&self) -> Result<(), ValidationError> { @@ -98,12 +212,12 @@ impl ValidateBasic for CommitSig { /// An extension trait for the [`Commit`] to perform additional actions. /// -/// [`Commit`]: celestia_tendermint::block::Commit +/// [`Commit`]: tendermint::block::Commit pub trait CommitExt { /// Get the signed [`Vote`] from the [`Commit`] at the given index. /// - /// [`Commit`]: celestia_tendermint::block::Commit - /// [`Vote`]: celestia_tendermint::Vote + /// [`Commit`]: tendermint::block::Commit + /// [`Vote`]: tendermint::Vote fn vote_sign_bytes(&self, chain_id: &chain::Id, signature_idx: usize) -> Result>; } @@ -141,9 +255,11 @@ impl CommitExt for Commit { validator_address, validator_index: signature_idx.try_into()?, signature, + extension: Vec::new(), + extension_signature: None, }; - Ok(vote.to_signable_vec(chain_id.clone())?) + Ok(vote.into_signable_vec(chain_id.clone())) } } @@ -163,7 +279,7 @@ mod tests { fn sample_commit() -> Commit { serde_json::from_str(r#"{ - "height": 1, + "height": "1", "round": 0, "block_id": { "hash": "17F7D5108753C39714DCA67E6A73CE855C6EA9B0071BBD4FFE5D2EF7F3973BFC", diff --git a/types/src/block/data.rs b/types/src/block/data.rs new file mode 100644 index 00000000..c78caccc --- /dev/null +++ b/types/src/block/data.rs @@ -0,0 +1,47 @@ +use celestia_proto::tendermint_celestia_mods::types::Data as RawData; +use serde::{Deserialize, Serialize}; +use tendermint_proto::Protobuf; + +use crate::Error; + +/// Data contained in a [`Block`]. +/// +/// [`Block`]: crate::block::Block +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(try_from = "RawData", into = "RawData")] +pub struct Data { + /// Transactions. + pub txs: Vec>, + + /// Square width of original data square. + pub square_size: u64, + + /// Hash is the root of a binary Merkle tree where the leaves of the tree are + /// the row and column roots of an extended data square. Hash is often referred + /// to as the "data root". + pub hash: Vec, +} + +impl Protobuf for Data {} + +impl TryFrom for Data { + type Error = Error; + + fn try_from(value: RawData) -> Result { + Ok(Data { + txs: value.txs, + square_size: value.square_size, + hash: value.hash, + }) + } +} + +impl From for RawData { + fn from(value: Data) -> RawData { + RawData { + txs: value.txs, + square_size: value.square_size, + hash: value.hash, + } + } +} diff --git a/types/src/byzantine.rs b/types/src/byzantine.rs index 2616b861..cb6af55d 100644 --- a/types/src/byzantine.rs +++ b/types/src/byzantine.rs @@ -1,13 +1,13 @@ use celestia_proto::share::eds::byzantine::pb::BadEncoding as RawBadEncodingFraudProof; use celestia_proto::share::eds::byzantine::pb::Share as RawShareWithProof; -use celestia_tendermint::{block::Height, Hash}; -use celestia_tendermint_proto::Protobuf; -use serde::{Deserialize, Serialize}; +use tendermint::block::Height; +use tendermint_proto::Protobuf; use crate::bail_validation; use crate::consts::appconsts; use crate::eds::AxisType; use crate::fraud_proof::FraudProof; +use crate::hash::Hash; use crate::nmt::{Namespace, NamespaceProof, Nmt, NmtExt, NS_SIZE}; use crate::{Error, ExtendedHeader, Result}; @@ -25,11 +25,7 @@ use crate::{Error, ExtendedHeader, Result}; /// [`Data Availability Sampling`]: https://docs.celestia.org/learn/how-celestia-works/data-availability-layer /// [`ExtendedDataSquare`]: crate::ExtendedDataSquare /// [`Share`]: crate::share::Share -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde( - try_from = "RawBadEncodingFraudProof", - into = "RawBadEncodingFraudProof" -)] +#[derive(Debug, Clone, PartialEq)] pub struct BadEncodingFraudProof { header_hash: Hash, block_height: Height, diff --git a/types/src/consts.rs b/types/src/consts.rs index 840dbac6..9bef0edc 100644 --- a/types/src/consts.rs +++ b/types/src/consts.rs @@ -1,7 +1,7 @@ //! Constants used within celestia ecosystem. /// The size of the SHA256 hash. -pub const HASH_SIZE: usize = celestia_tendermint::hash::SHA256_HASH_SIZE; +pub const HASH_SIZE: usize = tendermint::hash::SHA256_HASH_SIZE; // celestia-core/types/genesis /// Constants related to genesis definition. diff --git a/types/src/data_availability_header.rs b/types/src/data_availability_header.rs index a552edbb..dbe5e2ac 100644 --- a/types/src/data_availability_header.rs +++ b/types/src/data_availability_header.rs @@ -1,11 +1,11 @@ use std::ops::RangeInclusive; use celestia_proto::celestia::core::v1::da::DataAvailabilityHeader as RawDataAvailabilityHeader; -use celestia_tendermint::merkle::simple_hash_from_byte_vectors; -use celestia_tendermint_proto::v0_34::types::RowProof as RawRowProof; -use celestia_tendermint_proto::Protobuf; +use celestia_proto::celestia::core::v1::proof::RowProof as RawRowProof; use serde::{Deserialize, Serialize}; use sha2::Sha256; +use tendermint::merkle::simple_hash_from_byte_vectors; +use tendermint_proto::Protobuf; use crate::consts::appconsts::AppVersion; use crate::consts::data_availability_header::{ @@ -165,7 +165,7 @@ impl DataAvailabilityHeader { /// let eh = get_extended_header(); /// let dah = eh.dah; /// - /// assert_eq!(dah.hash(), eh.header.data_hash); + /// assert_eq!(dah.hash(), eh.header.data_hash.unwrap()); /// ``` pub fn hash(&self) -> Hash { let all_roots: Vec<_> = self diff --git a/types/src/eds.rs b/types/src/eds.rs index 581d3e49..706a40dc 100644 --- a/types/src/eds.rs +++ b/types/src/eds.rs @@ -449,7 +449,7 @@ impl ExtendedDataSquare { #[derive(Serialize, Deserialize)] pub struct RawExtendedDataSquare { /// The raw data of the EDS. - #[serde(with = "celestia_tendermint_proto::serializers::bytes::vec_base64string")] + #[serde(with = "tendermint_proto::serializers::bytes::vec_base64string")] pub data_square: Vec>, /// The codec used to encode parity shares. pub codec: String, diff --git a/types/src/error.rs b/types/src/error.rs index c8475241..a19b3152 100644 --- a/types/src/error.rs +++ b/types/src/error.rs @@ -22,13 +22,13 @@ pub enum Error { #[error("Invalid namespace size")] InvalidNamespaceSize, - /// Error propagated from the [`celestia_tendermint`]. + /// Error propagated from the [`tendermint`]. #[error(transparent)] - Tendermint(#[from] celestia_tendermint::Error), + Tendermint(#[from] tendermint::Error), - /// Error propagated from the [`celestia_tendermint_proto`]. + /// Error propagated from the [`tendermint_proto`]. #[error(transparent)] - Protobuf(#[from] celestia_tendermint_proto::Error), + Protobuf(#[from] tendermint_proto::Error), /// Error propagated from the [`cid::multihash`]. #[error(transparent)] @@ -255,7 +255,7 @@ pub enum Error { impl From for Error { fn from(value: prost::DecodeError) -> Self { - Error::Protobuf(celestia_tendermint_proto::Error::decode_message(value)) + Error::Protobuf(tendermint_proto::Error::decode_message(value)) } } diff --git a/types/src/extended_header.rs b/types/src/extended_header.rs index 3211cfb3..828a32aa 100644 --- a/types/src/extended_header.rs +++ b/types/src/extended_header.rs @@ -6,14 +6,15 @@ use std::fmt::{Display, Formatter}; use std::time::Duration; use celestia_proto::header::pb::ExtendedHeader as RawExtendedHeader; -use celestia_tendermint::block::header::Header; -use celestia_tendermint::block::{Commit, Height}; -use celestia_tendermint::chain::id::Id; -use celestia_tendermint::{validator, Hash, Time}; -use celestia_tendermint_proto::Protobuf; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use tendermint::block::header::Header; +use tendermint::block::{Commit, Height}; +use tendermint::chain::id::Id; +use tendermint::{validator, Time}; +use tendermint_proto::Protobuf; use crate::consts::appconsts::AppVersion; +use crate::hash::Hash; use crate::trust_level::DEFAULT_TRUST_LEVEL; use crate::validator_set::ValidatorSetExt; use crate::{ @@ -59,8 +60,7 @@ const VERIFY_CLOCK_DRIFT: Duration = Duration::from_secs(10); /// fetched_header.validate().expect("Invalid block header"); /// genesis_header.verify(&fetched_header).expect("Malicious header received"); /// ``` -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(try_from = "RawExtendedHeader", into = "RawExtendedHeader")] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ExtendedHeader { /// Tendermint block header. pub header: Header, @@ -164,11 +164,11 @@ impl ExtendedHeader { } // ensure data root from raw header matches computed root - if self.dah.hash() != self.header.data_hash { + if self.dah.hash() != self.header.data_hash.unwrap_or_default() { bail_validation!( "dah hash ({}) != header dah hash ({})", self.dah.hash(), - self.header.data_hash, + self.header.data_hash.unwrap_or_default(), ) } @@ -428,6 +428,97 @@ impl From for RawExtendedHeader { } } +mod custom_serde { + use celestia_proto::celestia::core::v1::da::DataAvailabilityHeader; + use celestia_proto::header::pb::ExtendedHeader as RawExtendedHeader; + use serde::{Deserialize, Serialize}; + use tendermint_proto::v0_34::types::Commit as RawCommit; + use tendermint_proto::v0_34::types::{BlockId, CommitSig, Header, ValidatorSet}; + + #[derive(Deserialize, Serialize)] + pub(super) struct SerdeExtendedHeader { + header: Option
, + commit: Option, + validator_set: Option, + dah: Option, + } + + #[derive(Deserialize, Serialize)] + pub(super) struct SerdeCommit { + height: i64, + round: i32, + block_id: Option, + #[serde(with = "tendermint_proto::serializers::nullable")] + signatures: Vec, + } + + impl From for SerdeExtendedHeader { + fn from(value: RawExtendedHeader) -> Self { + SerdeExtendedHeader { + header: value.header, + commit: value.commit.map(|commit| commit.into()), + validator_set: value.validator_set, + dah: value.dah, + } + } + } + + impl From for RawExtendedHeader { + fn from(value: SerdeExtendedHeader) -> Self { + RawExtendedHeader { + header: value.header, + commit: value.commit.map(|commit| commit.into()), + validator_set: value.validator_set, + dah: value.dah, + } + } + } + + impl From for SerdeCommit { + fn from(value: RawCommit) -> Self { + SerdeCommit { + height: value.height, + round: value.round, + block_id: value.block_id, + signatures: value.signatures, + } + } + } + + impl From for RawCommit { + fn from(value: SerdeCommit) -> Self { + RawCommit { + height: value.height, + round: value.round, + block_id: value.block_id, + signatures: value.signatures, + } + } + } +} + +impl Serialize for ExtendedHeader { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let pb: RawExtendedHeader = self.clone().into(); + let custom_ser: custom_serde::SerdeExtendedHeader = pb.into(); + custom_ser.serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for ExtendedHeader { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let custom_de = custom_serde::SerdeExtendedHeader::deserialize(deserializer)?; + let pb: RawExtendedHeader = custom_de.into(); + ExtendedHeader::try_from(pb).map_err(serde::de::Error::custom) + } +} + #[cfg(test)] mod tests { use super::*; @@ -493,7 +584,7 @@ mod tests { #[test] fn validate_dah_hash_mismatch() { let mut eh = sample_eh_chain_1_block_27(); - eh.header.data_hash = Hash::Sha256([0; 32]); + eh.header.data_hash = Some(Hash::Sha256([0; 32])); eh.validate().unwrap_err(); } diff --git a/types/src/fraud_proof.rs b/types/src/fraud_proof.rs index 04d6e649..1199ff46 100644 --- a/types/src/fraud_proof.rs +++ b/types/src/fraud_proof.rs @@ -2,14 +2,12 @@ //! //! A fraud proof is a proof of the detected malicious action done to the network. -use std::convert::Infallible; - -use celestia_tendermint::block::Height; -use celestia_tendermint::Hash; -use celestia_tendermint_proto::Protobuf; use serde::{Deserialize, Serialize, Serializer}; +use tendermint::block::Height; +use tendermint_proto::Protobuf; pub use crate::byzantine::BadEncodingFraudProof; +use crate::hash::Hash; use crate::{Error, ExtendedHeader, Result}; /// A proof of the malicious actions done to the network. @@ -38,7 +36,7 @@ pub trait FraudProof { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct RawFraudProof { proof_type: String, - #[serde(with = "celestia_tendermint_proto::serializers::bytes::base64string")] + #[serde(with = "tendermint_proto::serializers::bytes::base64string")] data: Vec, } @@ -70,13 +68,10 @@ impl TryFrom for Proof { impl From<&Proof> for RawFraudProof { fn from(value: &Proof) -> Self { match value { - Proof::BadEncoding(befp) => { - let encoded: Result<_, Infallible> = befp.encode_vec(); - RawFraudProof { - proof_type: BadEncodingFraudProof::TYPE.to_owned(), - data: encoded.unwrap(), - } - } + Proof::BadEncoding(befp) => RawFraudProof { + proof_type: BadEncodingFraudProof::TYPE.to_owned(), + data: befp.clone().encode_vec(), + }, } } } diff --git a/types/src/hash.rs b/types/src/hash.rs index 47baaf0e..d11cd2c4 100644 --- a/types/src/hash.rs +++ b/types/src/hash.rs @@ -1,7 +1,7 @@ //! Celestia hash related types and traits. /// The hash type used commonly in the Celestia. -pub type Hash = celestia_tendermint::hash::Hash; +pub type Hash = tendermint::hash::Hash; /// A trait extending [`Hash`] functionality. /// diff --git a/types/src/lib.rs b/types/src/lib.rs index b7c87fb7..4beeb4f9 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -2,7 +2,7 @@ #![doc = include_str!("../README.md")] pub mod blob; -mod block; +pub mod block; mod byzantine; pub mod consts; mod data_availability_header; @@ -19,6 +19,7 @@ pub mod p2p; pub mod row; pub mod row_namespace_data; pub mod sample; +pub mod serializers; mod share; pub mod state; mod sync; @@ -31,7 +32,7 @@ mod validate; mod validator_set; pub use crate::blob::{Blob, Commitment}; -pub use crate::block::*; +pub use crate::block::Height; pub use crate::consts::appconsts::AppVersion; pub use crate::data_availability_header::*; pub use crate::eds::{AxisType, ExtendedDataSquare}; diff --git a/types/src/merkle_proof.rs b/types/src/merkle_proof.rs index c3288124..9635710d 100644 --- a/types/src/merkle_proof.rs +++ b/types/src/merkle_proof.rs @@ -1,7 +1,8 @@ -use celestia_tendermint::crypto::default::Sha256; -use celestia_tendermint::merkle::{Hash, MerkleHash}; -use celestia_tendermint_proto::{v0_34::crypto::Proof as RawMerkleProof, Protobuf}; +use celestia_proto::celestia::core::v1::proof::Proof as RawMerkleProof; use serde::{Deserialize, Serialize}; +use tendermint::crypto::default::Sha256; +use tendermint::merkle::{Hash, MerkleHash}; +use tendermint_proto::Protobuf; use crate::{ bail_validation, bail_verification, validation_error, verification_error, Error, Result, @@ -211,8 +212,8 @@ impl From for RawMerkleProof { #[cfg(test)] mod tests { - use celestia_tendermint::crypto::default::Sha256; - use celestia_tendermint::merkle::simple_hash_from_byte_vectors; + use tendermint::crypto::default::Sha256; + use tendermint::merkle::simple_hash_from_byte_vectors; use crate::test_utils::random_bytes; diff --git a/types/src/nmt.rs b/types/src/nmt.rs index c3d8d0c2..920a9922 100644 --- a/types/src/nmt.rs +++ b/types/src/nmt.rs @@ -19,11 +19,11 @@ use base64::prelude::*; use blockstore::block::CidError; -use celestia_tendermint::hash::SHA256_HASH_SIZE; -use celestia_tendermint_proto::serializers::cow_str::CowStr; +use celestia_proto::serializers::cow_str::CowStr; use cid::CidGeneric; use multihash::Multihash; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use tendermint::hash::SHA256_HASH_SIZE; mod namespace_proof; mod namespaced_hash; diff --git a/types/src/nmt/namespace_proof.rs b/types/src/nmt/namespace_proof.rs index 5fe6e446..263fbb3a 100644 --- a/types/src/nmt/namespace_proof.rs +++ b/types/src/nmt/namespace_proof.rs @@ -1,10 +1,10 @@ use std::ops::{Deref, DerefMut}; +use celestia_proto::celestia::core::v1::proof::NmtProof as RawNmtProof; use celestia_proto::proof::pb::Proof as RawProof; -use celestia_tendermint_proto::v0_34::types::NmtProof as RawTendermintProof; -use celestia_tendermint_proto::Protobuf; use nmt_rs::simple_merkle::proof::Proof as NmtProof; use serde::{Deserialize, Serialize}; +use tendermint_proto::Protobuf; use crate::nmt::{NamespacedHash, NamespacedHashExt, NamespacedSha2Hasher, NS_SIZE}; use crate::{Error, Result}; @@ -179,10 +179,10 @@ impl From for RawProof { } } -impl TryFrom for NamespaceProof { +impl TryFrom for NamespaceProof { type Error = Error; - fn try_from(value: RawTendermintProof) -> Result { + fn try_from(value: RawNmtProof) -> Result { let raw_proof = RawProof { start: value.start as i64, end: value.end as i64, @@ -195,10 +195,10 @@ impl TryFrom for NamespaceProof { } } -impl From for RawTendermintProof { +impl From for RawNmtProof { fn from(value: NamespaceProof) -> Self { let raw_proof = RawProof::from(value); - RawTendermintProof { + RawNmtProof { start: raw_proof.start as i32, end: raw_proof.end as i32, nodes: raw_proof.nodes, diff --git a/types/src/p2p.rs b/types/src/p2p.rs index 66f2c1ed..0fee378f 100644 --- a/types/src/p2p.rs +++ b/types/src/p2p.rs @@ -58,7 +58,7 @@ pub struct ResourceManagerStats { /// [`PeerId`]: libp2p_identity::PeerId #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub struct PeerId( - #[serde(with = "celestia_tendermint_proto::serializers::from_str")] pub libp2p_identity::PeerId, + #[serde(with = "tendermint_proto::serializers::from_str")] pub libp2p_identity::PeerId, ); impl From for PeerId { diff --git a/types/src/serializers.rs b/types/src/serializers.rs new file mode 100644 index 00000000..47e93e1e --- /dev/null +++ b/types/src/serializers.rs @@ -0,0 +1,3 @@ +//! Custom serializers to be used with [`serde`]. + +pub mod hash; diff --git a/types/src/serializers/hash.rs b/types/src/serializers/hash.rs new file mode 100644 index 00000000..d3dba130 --- /dev/null +++ b/types/src/serializers/hash.rs @@ -0,0 +1,24 @@ +//! Custom [`serde`] serializer for [`tendermint::hash::Hash`]. + +use std::str::FromStr; + +use celestia_proto::serializers::cow_str::CowStr; +use serde::{Deserialize, Deserializer, Serializer}; +use tendermint::hash::Hash; + +/// Deserialize [`tendermint::hash::Hash`]. +pub fn deserialize<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let hex = Option::::deserialize(deserializer)?.unwrap_or_default(); + Hash::from_str(&hex).map_err(serde::de::Error::custom) +} + +/// Serialize [`tendermint::hash::Hash`]. +pub fn serialize(value: &Hash, serializer: S) -> Result +where + S: Serializer, +{ + serializer.serialize_some(&value.to_string()) +} diff --git a/types/src/share/proof.rs b/types/src/share/proof.rs index 92d38818..5c1d77dc 100644 --- a/types/src/share/proof.rs +++ b/types/src/share/proof.rs @@ -1,9 +1,9 @@ -use celestia_tendermint::Hash; -use celestia_tendermint_proto::v0_34::types::ShareProof as RawShareProof; -use celestia_tendermint_proto::Protobuf; +use celestia_proto::celestia::core::v1::proof::ShareProof as RawShareProof; use serde::{Deserialize, Serialize}; +use tendermint_proto::Protobuf; use crate::consts::appconsts::SHARE_SIZE; +use crate::hash::Hash; use crate::nmt::NamespaceProof; use crate::{bail_verification, validation_error, RowProof}; use crate::{nmt::Namespace, Error, Result}; diff --git a/types/src/state/address.rs b/types/src/state/address.rs index 48e4dfe7..88f19f47 100644 --- a/types/src/state/address.rs +++ b/types/src/state/address.rs @@ -2,9 +2,9 @@ use std::fmt::Display; use std::str::FromStr; use bech32::Hrp; -use celestia_tendermint::account::Id; use enum_dispatch::enum_dispatch; use serde::{Deserialize, Serialize}; +use tendermint::account::Id; use crate::consts::cosmos::*; use crate::{Error, Result}; @@ -88,7 +88,7 @@ pub struct ConsAddress { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(transparent)] struct Raw { - #[serde(with = "celestia_tendermint_proto::serializers::from_str")] + #[serde(with = "tendermint_proto::serializers::from_str")] addr: String, } diff --git a/types/src/state/auth.rs b/types/src/state/auth.rs index 18b9ec6b..cef72dfd 100644 --- a/types/src/state/auth.rs +++ b/types/src/state/auth.rs @@ -1,15 +1,11 @@ //! types related to accounts -#[cfg(feature = "tonic")] -use pbjson_types::Any; -use prost::Message; -#[cfg(not(feature = "tonic"))] -use prost_types::Any; - use celestia_proto::cosmos::crypto::ed25519::PubKey as Ed25519PubKey; use celestia_proto::cosmos::crypto::secp256k1::PubKey as Secp256k1PubKey; -use celestia_tendermint::public_key::PublicKey; -use celestia_tendermint_proto::Protobuf; +use prost::Message; +use tendermint::public_key::PublicKey; +use tendermint_proto::google::protobuf::Any; +use tendermint_proto::Protobuf; use crate::state::Address; use crate::Error; @@ -123,16 +119,14 @@ fn any_from_public_key(key: PublicKey) -> Any { value: Ed25519PubKey { key: key.to_bytes(), } - .encode_to_vec() - .into(), + .encode_to_vec(), }, key @ PublicKey::Secp256k1(_) => Any { type_url: COSMOS_SECP256K1_PUBKEY.to_string(), value: Secp256k1PubKey { key: key.to_bytes(), } - .encode_to_vec() - .into(), + .encode_to_vec(), }, _ => unimplemented!("unexpected key type"), } diff --git a/types/src/state/tx.rs b/types/src/state/tx.rs index a4491538..624fd69b 100644 --- a/types/src/state/tx.rs +++ b/types/src/state/tx.rs @@ -1,12 +1,8 @@ -use celestia_tendermint_proto::Protobuf; -#[cfg(feature = "tonic")] -use pbjson_types::Any; -#[cfg(not(feature = "tonic"))] -use prost_types::Any; -use serde::{Deserialize, Serialize}; - use celestia_proto::cosmos::base::abci::v1beta1::AbciMessageLog; -use celestia_tendermint_proto::v0_34::abci::Event; +use serde::{Deserialize, Serialize}; +use tendermint_proto::google::protobuf::Any; +use tendermint_proto::v0_34::abci::Event; +use tendermint_proto::Protobuf; use crate::state::bit_array::BitVector; use crate::Error; diff --git a/types/src/sync.rs b/types/src/sync.rs index 36c57937..041f95b3 100644 --- a/types/src/sync.rs +++ b/types/src/sync.rs @@ -1,6 +1,7 @@ -use celestia_tendermint::hash::Hash; -use celestia_tendermint::time::Time; use serde::{Deserialize, Serialize}; +use tendermint::time::Time; + +use crate::hash::Hash; /// A state of the blockchain synchronization. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] @@ -14,8 +15,10 @@ pub struct SyncState { /// The last height to be synced. pub to_height: u64, /// The first hash to be synced. + #[serde(with = "crate::serializers::hash")] pub from_hash: Hash, /// The last hash to be synced. + #[serde(with = "crate::serializers::hash")] pub to_hash: Hash, /// The time when syncing began. pub start: Time, diff --git a/types/src/test_utils.rs b/types/src/test_utils.rs index 00c75d8a..36960b5c 100644 --- a/types/src/test_utils.rs +++ b/types/src/test_utils.rs @@ -1,12 +1,12 @@ //! Utilities for writing tests. use std::time::Duration; -use celestia_tendermint::block::header::{Header, Version}; -use celestia_tendermint::block::{parts, Commit, CommitSig}; -use celestia_tendermint::public_key::PublicKey; -use celestia_tendermint::{chain, Signature, Time}; use ed25519_consensus::SigningKey; use rand::RngCore; +use tendermint::block::header::{Header, Version}; +use tendermint::block::{parts, Commit, CommitSig}; +use tendermint::public_key::PublicKey; +use tendermint::{chain, Signature, Time}; use crate::block::{CommitExt, GENESIS_HEIGHT}; pub use crate::byzantine::test_utils::corrupt_eds; @@ -330,19 +330,19 @@ pub fn unverify(header: &mut ExtendedHeader) { let key = SigningKey::new(rand::thread_rng()); let pub_key_bytes = key.verification_key().to_bytes(); let pub_key = PublicKey::from_raw_ed25519(&pub_key_bytes).unwrap(); - let validator_address = celestia_tendermint::account::Id::new(rand::random()); + let validator_address = tendermint::account::Id::new(rand::random()); header.header.proposer_address = validator_address; header.validator_set = ValidatorSet::new( - vec![celestia_tendermint::validator::Info { + vec![tendermint::validator::Info { address: validator_address, pub_key, power: 5000_u32.into(), name: None, proposer_priority: 0_i64.into(), }], - Some(celestia_tendermint::validator::Info { + Some(tendermint::validator::Info { address: validator_address, pub_key, power: 5000_u32.into(), @@ -478,12 +478,12 @@ fn generate_new( let pub_key_bytes = signing_key.verification_key().to_bytes(); let pub_key = PublicKey::from_raw_ed25519(&pub_key_bytes).unwrap(); - let validator_address = celestia_tendermint::account::Id::new(rand::random()); + let validator_address = tendermint::account::Id::new(rand::random()); let last_block_id = if height == GENESIS_HEIGHT { None } else { - Some(celestia_tendermint::block::Id { + Some(tendermint::block::Id { hash: Hash::Sha256(rand::random()), part_set_header: parts::Header::new(1, Hash::Sha256(rand::random())) .expect("invalid PartSetHeader"), @@ -500,8 +500,8 @@ fn generate_new( height: height.try_into().unwrap(), time, last_block_id, - last_commit_hash: Hash::default_sha256(), - data_hash: Hash::None, + last_commit_hash: Some(Hash::default_sha256()), + data_hash: Some(Hash::None), validators_hash: Hash::None, next_validators_hash: Hash::None, consensus_hash: Hash::Sha256(rand::random()), @@ -510,14 +510,14 @@ fn generate_new( .to_vec() .try_into() .unwrap(), - last_results_hash: Hash::default_sha256(), - evidence_hash: Hash::default_sha256(), + last_results_hash: Some(Hash::default_sha256()), + evidence_hash: Some(Hash::default_sha256()), proposer_address: validator_address, }, commit: Commit { height: height.try_into().unwrap(), round: 0_u16.into(), - block_id: celestia_tendermint::block::Id { + block_id: tendermint::block::Id { hash: Hash::None, part_set_header: parts::Header::new(1, Hash::Sha256(rand::random())) .expect("invalid PartSetHeader"), @@ -529,14 +529,14 @@ fn generate_new( }], }, validator_set: ValidatorSet::new( - vec![celestia_tendermint::validator::Info { + vec![tendermint::validator::Info { address: validator_address, pub_key, power: 5000_u32.into(), name: None, proposer_priority: 0_i64.into(), }], - Some(celestia_tendermint::validator::Info { + Some(tendermint::validator::Info { address: validator_address, pub_key, power: 5000_u32.into(), @@ -571,7 +571,7 @@ fn generate_next( let last_block_id = if increment == 1 { Some(current.commit.block_id) } else { - Some(celestia_tendermint::block::Id { + Some(tendermint::block::Id { hash: Hash::Sha256(rand::random()), part_set_header: parts::Header::new(1, Hash::Sha256(rand::random())) .expect("invalid PartSetHeader"), @@ -585,8 +585,8 @@ fn generate_next( height, time, last_block_id, - last_commit_hash: Hash::default_sha256(), - data_hash: Hash::None, + last_commit_hash: Some(Hash::default_sha256()), + data_hash: Some(Hash::None), validators_hash: Hash::None, next_validators_hash: Hash::None, consensus_hash: Hash::Sha256(rand::random()), @@ -595,14 +595,14 @@ fn generate_next( .to_vec() .try_into() .unwrap(), - last_results_hash: Hash::default_sha256(), - evidence_hash: Hash::default_sha256(), + last_results_hash: Some(Hash::default_sha256()), + evidence_hash: Some(Hash::default_sha256()), proposer_address: validator_address, }, commit: Commit { height, round: 0_u16.into(), - block_id: celestia_tendermint::block::Id { + block_id: tendermint::block::Id { hash: Hash::None, part_set_header: parts::Header::new(1, Hash::Sha256(rand::random())) .expect("invalid PartSetHeader"), @@ -627,7 +627,7 @@ fn generate_next( fn hash_and_sign(header: &mut ExtendedHeader, signing_key: &SigningKey) { header.header.validators_hash = header.validator_set.hash(); header.header.next_validators_hash = header.validator_set.hash(); - header.header.data_hash = header.dah.hash(); + header.header.data_hash = Some(header.dah.hash()); header.commit.block_id.hash = header.header.hash(); let vote_sign = header diff --git a/types/src/validator_set.rs b/types/src/validator_set.rs index 7af7fcfc..afb27547 100644 --- a/types/src/validator_set.rs +++ b/types/src/validator_set.rs @@ -1,14 +1,14 @@ use std::collections::HashMap; -use celestia_tendermint::block::CommitSig; -use celestia_tendermint::crypto::default::signature::Verifier; -use celestia_tendermint::validator::{Info, Set}; -use celestia_tendermint::{account, block, chain}; +use tendermint::block::CommitSig; +use tendermint::crypto::default::signature::Verifier; +use tendermint::validator::{Info, Set}; +use tendermint::{account, block, chain}; +use crate::block::CommitExt; use crate::trust_level::TrustLevelRatio; use crate::{ - bail_validation, bail_verification, CommitExt, Result, ValidateBasic, ValidationError, - VerificationError, + bail_validation, bail_verification, Result, ValidateBasic, ValidationError, VerificationError, }; impl ValidateBasic for Set { @@ -162,14 +162,14 @@ fn find_validator<'a>(vals: &'a Set, val_id: &account::Id) -> Option<(usize, &'a mod tests { use super::*; - use celestia_tendermint_proto::v0_34::types::ValidatorSet as RawValidatorSet; + use tendermint_proto::v0_34::types::ValidatorSet as RawValidatorSet; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::wasm_bindgen_test as test; fn sample_commit() -> block::Commit { serde_json::from_str(r#"{ - "height": 1, + "height": "1", "round": 0, "block_id": { "hash": "17F7D5108753C39714DCA67E6A73CE855C6EA9B0071BBD4FFE5D2EF7F3973BFC",