types: add BlockCompleteEntry (#230)
Some checks failed
Audit / audit (push) Has been cancelled
CI / fmt (push) Has been cancelled
CI / typo (push) Has been cancelled
CI / ci (macos-latest, stable, bash) (push) Has been cancelled
CI / ci (ubuntu-latest, stable, bash) (push) Has been cancelled
CI / ci (windows-latest, stable-x86_64-pc-windows-gnu, msys2 {0}) (push) Has been cancelled
Deny / audit (push) Has been cancelled
Doc / build (push) Has been cancelled
Doc / deploy (push) Has been cancelled

* types: add `block_complete_entry.rs`

* net: fix imports

* p2p: fix imports

* turn off default-features

* p2p: fix imports

* Update net/wire/Cargo.toml

Co-authored-by: Boog900 <boog900@tutanota.com>

* wire: re-export types

---------

Co-authored-by: Boog900 <boog900@tutanota.com>
This commit is contained in:
hinto-janai 2024-07-16 17:47:50 -04:00 committed by GitHub
parent 0910c0a231
commit 6820da9848
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 190 additions and 146 deletions

6
Cargo.lock generated
View file

@ -702,6 +702,7 @@ dependencies = [
"cuprate-p2p-core", "cuprate-p2p-core",
"cuprate-pruning", "cuprate-pruning",
"cuprate-test-utils", "cuprate-test-utils",
"cuprate-types",
"cuprate-wire", "cuprate-wire",
"dashmap", "dashmap",
"futures", "futures",
@ -800,8 +801,12 @@ version = "0.0.0"
name = "cuprate-types" name = "cuprate-types"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"bytes",
"cuprate-epee-encoding",
"cuprate-fixed-bytes",
"curve25519-dalek", "curve25519-dalek",
"monero-serai", "monero-serai",
"serde",
] ]
[[package]] [[package]]
@ -813,6 +818,7 @@ dependencies = [
"cuprate-epee-encoding", "cuprate-epee-encoding",
"cuprate-fixed-bytes", "cuprate-fixed-bytes",
"cuprate-levin", "cuprate-levin",
"cuprate-types",
"hex", "hex",
"thiserror", "thiserror",
] ]

View file

@ -14,6 +14,7 @@ tracing = ["cuprate-levin/tracing"]
cuprate-levin = { path = "../levin" } cuprate-levin = { path = "../levin" }
cuprate-epee-encoding = { path = "../epee-encoding" } cuprate-epee-encoding = { path = "../epee-encoding" }
cuprate-fixed-bytes = { path = "../fixed-bytes" } cuprate-fixed-bytes = { path = "../fixed-bytes" }
cuprate-types = { path = "../../types", default-features = false, features = ["epee"] }
bitflags = { workspace = true, features = ["std"] } bitflags = { workspace = true, features = ["std"] }
bytes = { workspace = true, features = ["std"] } bytes = { workspace = true, features = ["std"] }

View file

@ -16,10 +16,9 @@
//! Common types that are used across multiple messages. //! Common types that are used across multiple messages.
use bitflags::bitflags; use bitflags::bitflags;
use bytes::{Buf, BufMut, Bytes};
use cuprate_epee_encoding::{epee_object, EpeeValue, InnerMarker}; use cuprate_epee_encoding::epee_object;
use cuprate_fixed_bytes::ByteArray; pub use cuprate_types::{BlockCompleteEntry, PrunedTxBlobEntry, TransactionBlobs};
use crate::NetworkAddress; use crate::NetworkAddress;
@ -168,113 +167,6 @@ epee_object! {
rpc_credits_per_hash: u32 = 0_u32, rpc_credits_per_hash: u32 = 0_u32,
} }
/// A pruned tx with the hash of the missing prunable data
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PrunedTxBlobEntry {
/// The Tx
pub tx: Bytes,
/// The Prunable Tx Hash
pub prunable_hash: ByteArray<32>,
}
epee_object!(
PrunedTxBlobEntry,
tx: Bytes,
prunable_hash: ByteArray<32>,
);
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TransactionBlobs {
Pruned(Vec<PrunedTxBlobEntry>),
Normal(Vec<Bytes>),
None,
}
impl TransactionBlobs {
pub fn take_pruned(self) -> Option<Vec<PrunedTxBlobEntry>> {
match self {
TransactionBlobs::Normal(_) => None,
TransactionBlobs::Pruned(txs) => Some(txs),
TransactionBlobs::None => Some(vec![]),
}
}
pub fn take_normal(self) -> Option<Vec<Bytes>> {
match self {
TransactionBlobs::Normal(txs) => Some(txs),
TransactionBlobs::Pruned(_) => None,
TransactionBlobs::None => Some(vec![]),
}
}
pub fn len(&self) -> usize {
match self {
TransactionBlobs::Normal(txs) => txs.len(),
TransactionBlobs::Pruned(txs) => txs.len(),
TransactionBlobs::None => 0,
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
/// A Block that can contain transactions
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BlockCompleteEntry {
/// True if tx data is pruned
pub pruned: bool,
/// The Block
pub block: Bytes,
/// The Block Weight/Size
pub block_weight: u64,
/// The blocks txs
pub txs: TransactionBlobs,
}
epee_object!(
BlockCompleteEntry,
pruned: bool = false,
block: Bytes,
block_weight: u64 = 0_u64,
txs: TransactionBlobs = TransactionBlobs::None => tx_blob_read, tx_blob_write, should_write_tx_blobs,
);
fn tx_blob_read<B: Buf>(b: &mut B) -> cuprate_epee_encoding::Result<TransactionBlobs> {
let marker = cuprate_epee_encoding::read_marker(b)?;
match marker.inner_marker {
InnerMarker::Object => Ok(TransactionBlobs::Pruned(Vec::read(b, &marker)?)),
InnerMarker::String => Ok(TransactionBlobs::Normal(Vec::read(b, &marker)?)),
_ => Err(cuprate_epee_encoding::Error::Value(
"Invalid marker for tx blobs".to_string(),
)),
}
}
fn tx_blob_write<B: BufMut>(
val: TransactionBlobs,
field_name: &str,
w: &mut B,
) -> cuprate_epee_encoding::Result<()> {
if should_write_tx_blobs(&val) {
match val {
TransactionBlobs::Normal(bytes) => {
cuprate_epee_encoding::write_field(bytes, field_name, w)?
}
TransactionBlobs::Pruned(obj) => {
cuprate_epee_encoding::write_field(obj, field_name, w)?
}
TransactionBlobs::None => (),
}
}
Ok(())
}
fn should_write_tx_blobs(val: &TransactionBlobs) -> bool {
!val.is_empty()
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -23,7 +23,7 @@ use bytes::Bytes;
use cuprate_epee_encoding::{container_as_blob::ContainerAsBlob, epee_object}; use cuprate_epee_encoding::{container_as_blob::ContainerAsBlob, epee_object};
use cuprate_fixed_bytes::{ByteArray, ByteArrayVec}; use cuprate_fixed_bytes::{ByteArray, ByteArrayVec};
use super::common::BlockCompleteEntry; use crate::p2p::common::BlockCompleteEntry;
/// A block that SHOULD have transactions /// A block that SHOULD have transactions
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]

View file

@ -13,6 +13,7 @@ cuprate-address-book = { path = "../address-book" }
cuprate-pruning = { path = "../../pruning" } cuprate-pruning = { path = "../../pruning" }
cuprate-helper = { path = "../../helper", features = ["asynch"], default-features = false } cuprate-helper = { path = "../../helper", features = ["asynch"], default-features = false }
cuprate-async-buffer = { path = "../async-buffer" } cuprate-async-buffer = { path = "../async-buffer" }
cuprate-types = { path = "../../types", default-features = false }
monero-serai = { workspace = true, features = ["std"] } monero-serai = { workspace = true, features = ["std"] }

View file

@ -26,10 +26,8 @@ use cuprate_p2p_core::{
ProtocolResponse, ProtocolResponse,
}; };
use cuprate_pruning::PruningSeed; use cuprate_pruning::PruningSeed;
use cuprate_wire::{ use cuprate_types::{BlockCompleteEntry, TransactionBlobs};
common::{BlockCompleteEntry, TransactionBlobs}, use cuprate_wire::protocol::{ChainResponse, GetObjectsResponse};
protocol::{ChainResponse, GetObjectsResponse},
};
use crate::{ use crate::{
block_downloader::{download_blocks, BlockDownloaderConfig, ChainSvcRequest, ChainSvcResponse}, block_downloader::{download_blocks, BlockDownloaderConfig, ChainSvcRequest, ChainSvcResponse},

View file

@ -25,10 +25,8 @@ use tower::Service;
use cuprate_p2p_core::{ use cuprate_p2p_core::{
client::InternalPeerID, BroadcastMessage, ConnectionDirection, NetworkZone, client::InternalPeerID, BroadcastMessage, ConnectionDirection, NetworkZone,
}; };
use cuprate_wire::{ use cuprate_types::{BlockCompleteEntry, TransactionBlobs};
common::{BlockCompleteEntry, TransactionBlobs}, use cuprate_wire::protocol::{NewFluffyBlock, NewTransactions};
protocol::{NewFluffyBlock, NewTransactions},
};
use crate::constants::{ use crate::constants::{
DIFFUSION_FLUSH_AVERAGE_SECONDS_INBOUND, DIFFUSION_FLUSH_AVERAGE_SECONDS_OUTBOUND, DIFFUSION_FLUSH_AVERAGE_SECONDS_INBOUND, DIFFUSION_FLUSH_AVERAGE_SECONDS_OUTBOUND,

View file

@ -9,11 +9,18 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/types"
keywords = ["cuprate", "types"] keywords = ["cuprate", "types"]
[features] [features]
default = ["blockchain"] default = ["blockchain", "epee", "serde"]
blockchain = [] blockchain = []
epee = ["dep:cuprate-epee-encoding"]
serde = ["dep:serde"]
[dependencies] [dependencies]
cuprate-epee-encoding = { path = "../net/epee-encoding", optional = true }
cuprate-fixed-bytes = { path = "../net/fixed-bytes" }
bytes = { workspace = true }
curve25519-dalek = { workspace = true } curve25519-dalek = { workspace = true }
monero-serai = { workspace = true } monero-serai = { workspace = true }
serde = { workspace = true, features = ["derive"], optional = true }
[dev-dependencies] [dev-dependencies]

View file

@ -1,20 +1,11 @@
# `cuprate-types` # `cuprate-types`
Various data types shared by Cuprate. Shared data types within Cuprate.
- [1. File Structure](#1-file-structure) This crate is a kitchen-sink for data types that are shared across Cuprate.
- [1.1 `src/`](#11-src)
--- # Features flags
| Feature flag | Does what |
## 1. File Structure |--------------|-----------|
A quick reference of the structure of the folders & files in `cuprate-types`. | `blockchain` | Enables the `blockchain` module, containing the blockchain database request/response types
| `serde` | Enables `serde` on types where applicable
Note that `lib.rs/mod.rs` files are purely for re-exporting/visibility/lints, and contain no code. Each sub-directory has a corresponding `mod.rs`. | `epee` | Enables `cuprate-epee-encoding` on types where applicable
### 1.1 `src/`
The top-level `src/` files.
| File | Purpose |
|---------------------|---------|
| `service.rs` | Types used in database requests; `enum {Request,Response}`
| `types.rs` | Various general types used by Cuprate

View file

@ -0,0 +1,154 @@
//! Contains [`BlockCompleteEntry`] and the related types.
//---------------------------------------------------------------------------------------------------- Import
#[cfg(feature = "epee")]
use bytes::Bytes;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use cuprate_fixed_bytes::ByteArray;
#[cfg(feature = "epee")]
use cuprate_epee_encoding::{
epee_object,
macros::bytes::{Buf, BufMut},
EpeeValue, InnerMarker,
};
//---------------------------------------------------------------------------------------------------- BlockCompleteEntry
/// A block that can contain transactions.
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BlockCompleteEntry {
/// `true` if transaction data is pruned.
pub pruned: bool,
/// The block.
pub block: Bytes,
/// The block weight/size.
pub block_weight: u64,
/// The block's transactions.
pub txs: TransactionBlobs,
}
#[cfg(feature = "epee")]
epee_object!(
BlockCompleteEntry,
pruned: bool = false,
block: Bytes,
block_weight: u64 = 0_u64,
txs: TransactionBlobs = TransactionBlobs::None =>
TransactionBlobs::tx_blob_read,
TransactionBlobs::tx_blob_write,
TransactionBlobs::should_write_tx_blobs,
);
//---------------------------------------------------------------------------------------------------- TransactionBlobs
/// Transaction blobs within [`BlockCompleteEntry`].
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum TransactionBlobs {
/// Pruned transaction blobs.
Pruned(Vec<PrunedTxBlobEntry>),
/// Normal transaction blobs.
Normal(Vec<Bytes>),
#[default]
/// No transactions.
None,
}
impl TransactionBlobs {
/// Returns [`Some`] if `self` is [`Self::Pruned`].
pub fn take_pruned(self) -> Option<Vec<PrunedTxBlobEntry>> {
match self {
Self::Normal(_) => None,
Self::Pruned(txs) => Some(txs),
Self::None => Some(vec![]),
}
}
/// Returns [`Some`] if `self` is [`Self::Normal`].
pub fn take_normal(self) -> Option<Vec<Bytes>> {
match self {
Self::Normal(txs) => Some(txs),
Self::Pruned(_) => None,
Self::None => Some(vec![]),
}
}
/// Returns the byte length of the blob.
pub fn len(&self) -> usize {
match self {
Self::Normal(txs) => txs.len(),
Self::Pruned(txs) => txs.len(),
Self::None => 0,
}
}
/// Returns `true` if the byte length of the blob is `0`.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Epee read function.
#[cfg(feature = "epee")]
fn tx_blob_read<B: Buf>(b: &mut B) -> cuprate_epee_encoding::Result<Self> {
let marker = cuprate_epee_encoding::read_marker(b)?;
match marker.inner_marker {
InnerMarker::Object => Ok(Self::Pruned(Vec::read(b, &marker)?)),
InnerMarker::String => Ok(Self::Normal(Vec::read(b, &marker)?)),
_ => Err(cuprate_epee_encoding::Error::Value(
"Invalid marker for tx blobs".to_string(),
)),
}
}
/// Epee write function.
#[cfg(feature = "epee")]
fn tx_blob_write<B: BufMut>(
self,
field_name: &str,
w: &mut B,
) -> cuprate_epee_encoding::Result<()> {
if self.should_write_tx_blobs() {
match self {
Self::Normal(bytes) => {
cuprate_epee_encoding::write_field(bytes, field_name, w)?;
}
Self::Pruned(obj) => {
cuprate_epee_encoding::write_field(obj, field_name, w)?;
}
Self::None => (),
}
}
Ok(())
}
/// Epee should write function.
#[cfg(feature = "epee")]
fn should_write_tx_blobs(&self) -> bool {
!self.is_empty()
}
}
//---------------------------------------------------------------------------------------------------- PrunedTxBlobEntry
/// A pruned transaction with the hash of the missing prunable data
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct PrunedTxBlobEntry {
/// The transaction.
pub tx: Bytes,
/// The prunable transaction hash.
pub prunable_hash: ByteArray<32>,
}
#[cfg(feature = "epee")]
epee_object!(
PrunedTxBlobEntry,
tx: Bytes,
prunable_hash: ByteArray<32>,
);
//---------------------------------------------------------------------------------------------------- Import
#[cfg(test)]
mod tests {}

View file

@ -1,11 +1,4 @@
//! Cuprate shared data types. #![doc = include_str!("../README.md")]
//!
//! This crate is a kitchen-sink for data types that are shared across `Cuprate`.
//!
//! # Features flags
//! The [`blockchain`] module, containing the blockchain database request/response
//! types, must be enabled with the `blockchain` feature (on by default).
//---------------------------------------------------------------------------------------------------- Lints //---------------------------------------------------------------------------------------------------- Lints
// Forbid lints. // Forbid lints.
// Our code, and code generated (e.g macros) cannot overrule these. // Our code, and code generated (e.g macros) cannot overrule these.
@ -86,7 +79,10 @@
// //
// Documentation for each module is located in the respective file. // Documentation for each module is located in the respective file.
mod block_complete_entry;
mod types; mod types;
pub use block_complete_entry::{BlockCompleteEntry, PrunedTxBlobEntry, TransactionBlobs};
pub use types::{ pub use types::{
ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation,
}; };