diff --git a/Cargo.lock b/Cargo.lock index 31959a5f..4a1640b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,12 +29,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - [[package]] name = "android-tzdata" version = "0.1.1" @@ -115,15 +109,6 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bit-set" version = "0.5.3" @@ -150,10 +135,6 @@ name = "bitflags" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -dependencies = [ - "bytemuck", - "serde", -] [[package]] name = "bitvec" @@ -215,26 +196,6 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" -[[package]] -name = "bytemuck" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.60", -] - [[package]] name = "byteorder" version = "1.5.0" @@ -316,19 +277,6 @@ name = "crossbeam" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ "crossbeam-utils", ] @@ -352,15 +300,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "crossbeam-queue" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" version = "0.8.19" @@ -401,39 +340,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "cuprate-blockchain" -version = "0.0.0" -dependencies = [ - "bitflags 2.5.0", - "bytemuck", - "bytes", - "cfg-if", - "crossbeam", - "cuprate-helper", - "cuprate-test-utils", - "cuprate-types", - "curve25519-dalek", - "futures", - "heed", - "hex", - "hex-literal", - "monero-pruning", - "monero-serai", - "page_size", - "paste", - "pretty_assertions", - "rayon", - "redb", - "serde", - "tempfile", - "thiserror", - "thread_local", - "tokio", - "tokio-util", - "tower", -] - [[package]] name = "cuprate-consensus" version = "0.1.0" @@ -441,6 +347,7 @@ dependencies = [ "cuprate-consensus-rules", "cuprate-helper", "cuprate-test-utils", + "cuprate-types", "curve25519-dalek", "dalek-ff-group", "futures", @@ -508,7 +415,7 @@ dependencies = [ "fixed-bytes", "futures", "hex", - "indexmap 2.2.6", + "indexmap", "monero-address-book", "monero-p2p", "monero-pruning", @@ -557,11 +464,8 @@ version = "0.0.0" name = "cuprate-types" version = "0.0.0" dependencies = [ - "borsh", - "cfg-if", "curve25519-dalek", "monero-serai", - "serde", ] [[package]] @@ -632,7 +536,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown 0.14.5", + "hashbrown", "lock_api", "once_cell", "parking_lot_core", @@ -693,15 +597,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "doxygen-rs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "415b6ec780d34dcf624666747194393603d0373b7141eef01d12ee58881507d9" -dependencies = [ - "phf", -] - [[package]] name = "either" version = "1.11.0" @@ -808,15 +703,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "funty" version = "2.0.0" @@ -938,12 +824,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.5" @@ -951,17 +831,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", - "allocator-api2", -] - -[[package]] -name = "hdrhistogram" -version = "7.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" -dependencies = [ - "byteorder", - "num-traits", ] [[package]] @@ -970,44 +839,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "heed" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a300b0deeb2957162d7752b0f063b3be1c88333af5bb4e7a57d8fb3716f50b" -dependencies = [ - "bitflags 2.5.0", - "byteorder", - "heed-traits", - "heed-types", - "libc", - "lmdb-master-sys", - "once_cell", - "page_size", - "serde", - "synchronoise", - "url", -] - -[[package]] -name = "heed-traits" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3130048d404c57ce5a1ac61a903696e8fcde7e8c2991e9fcfc1f27c3ef74ff" - -[[package]] -name = "heed-types" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb0d6ba3700c9a57e83c013693e3eddb68a6d9b6781cacafc62a0d992e8ddb3" -dependencies = [ - "bincode", - "byteorder", - "heed-traits", - "serde", - "serde_json", -] - [[package]] name = "hermit-abi" version = "0.3.9" @@ -1155,26 +986,6 @@ dependencies = [ "cc", ] -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.2.6" @@ -1182,7 +993,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -1258,17 +1069,6 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" -[[package]] -name = "lmdb-master-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc9048db3a58c0732d7236abc4909058f9d2708cfb6d7d047eb895fddec6419a" -dependencies = [ - "cc", - "doxygen-rs", - "libc", -] - [[package]] name = "lock_api" version = "0.4.12" @@ -1340,7 +1140,7 @@ dependencies = [ "borsh", "cuprate-test-utils", "futures", - "indexmap 2.2.6", + "indexmap", "monero-p2p", "monero-pruning", "monero-wire", @@ -1500,16 +1300,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "page_size" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "parking" version = "2.2.0" @@ -1568,54 +1358,6 @@ dependencies = [ "sha2", ] -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.60", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project" version = "1.1.5" @@ -1842,15 +1584,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redb" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7508e692a49b6b2290b56540384ccae9b1fb4d77065640b165835b56ffe3bb" -dependencies = [ - "libc", -] - [[package]] name = "redox_syscall" version = "0.5.1" @@ -2148,12 +1881,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - [[package]] name = "slab" version = "0.4.9" @@ -2190,7 +1917,7 @@ name = "std-shims" version = "0.1.1" source = "git+https://github.com/Cuprate/serai.git?rev=d27d934#d27d93480aa8a849d84214ad4c71d83ce6fea0c1" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", "spin", ] @@ -2234,15 +1961,6 @@ dependencies = [ "syn 2.0.60", ] -[[package]] -name = "synchronoise" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dbc01390fc626ce8d1cffe3376ded2b72a11bb70e1c75f404a210e4daa4def2" -dependencies = [ - "crossbeam-queue", -] - [[package]] name = "tap" version = "1.0.1" @@ -2300,21 +2018,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.37.0" @@ -2376,10 +2079,7 @@ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", - "futures-io", "futures-sink", - "futures-util", - "hashbrown 0.14.5", "pin-project-lite", "slab", "tokio", @@ -2398,7 +2098,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap 2.2.6", + "indexmap", "toml_datetime", "winnow", ] @@ -2411,12 +2111,8 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", - "hdrhistogram", - "indexmap 1.9.3", "pin-project", "pin-project-lite", - "rand", - "slab", "tokio", "tokio-util", "tower-layer", @@ -2495,44 +2191,18 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "url" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - [[package]] name = "version_check" version = "0.9.4" @@ -2617,28 +2287,6 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows" version = "0.56.0" diff --git a/Cargo.toml b/Cargo.toml index d07f7bf4..b73d63af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ members = [ "p2p/dandelion", "p2p/monero-p2p", "p2p/address-book", - "storage/cuprate-blockchain", + #"storage/cuprate-blockchain", "storage/cuprate-txpool", "storage/database", "pruning", diff --git a/consensus/Cargo.toml b/consensus/Cargo.toml index 49236d9d..624eb637 100644 --- a/consensus/Cargo.toml +++ b/consensus/Cargo.toml @@ -10,6 +10,7 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus" [dependencies] cuprate-helper = { path = "../helper", default-features = false, features = ["std", "asynch", "num"] } cuprate-consensus-rules = { path = "./rules", features = ["rayon"] } +cuprate-types = { path = "../types" } thiserror = { workspace = true } tower = { workspace = true, features = ["util"] } diff --git a/consensus/rules/src/hard_forks.rs b/consensus/rules/src/hard_forks.rs index 5be1f9da..b34b93d7 100644 --- a/consensus/rules/src/hard_forks.rs +++ b/consensus/rules/src/hard_forks.rs @@ -163,6 +163,7 @@ impl HardFork { /// Returns the hard-fork for a blocks `major_version` field. /// /// + #[inline] pub fn from_version(version: u8) -> Result { Ok(match version { 1 => HardFork::V1, @@ -188,6 +189,7 @@ impl HardFork { /// Returns the hard-fork for a blocks `minor_version` (vote) field. /// /// + #[inline] pub fn from_vote(vote: u8) -> HardFork { if vote == 0 { // A vote of 0 is interpreted as 1 as that's what Monero used to default to. @@ -197,6 +199,7 @@ impl HardFork { Self::from_version(vote).unwrap_or(HardFork::V16) } + #[inline] pub fn from_block_header(header: &BlockHeader) -> Result<(HardFork, HardFork), HardForkError> { Ok(( HardFork::from_version(header.major_version)?, diff --git a/consensus/rules/src/transactions/contextual_data.rs b/consensus/rules/src/transactions/contextual_data.rs index 2c4943a3..6af3ad35 100644 --- a/consensus/rules/src/transactions/contextual_data.rs +++ b/consensus/rules/src/transactions/contextual_data.rs @@ -6,22 +6,13 @@ use std::{ use curve25519_dalek::EdwardsPoint; use monero_serai::transaction::{Input, Timelock}; -use crate::{transactions::TransactionError, HardFork, TxVersion}; - -/// An already approved previous transaction output. -#[derive(Debug, Copy, Clone)] -pub struct OutputOnChain { - pub height: u64, - pub time_lock: Timelock, - pub key: Option, - pub commitment: EdwardsPoint, -} +use crate::{transactions::TransactionError, HardFork}; /// Gets the absolute offsets from the relative offsets. /// /// This function will return an error if the relative offsets are empty. /// -fn get_absolute_offsets(relative_offsets: &[u64]) -> Result, TransactionError> { +pub fn get_absolute_offsets(relative_offsets: &[u64]) -> Result, TransactionError> { if relative_offsets.is_empty() { return Err(TransactionError::InputDoesNotHaveExpectedNumbDecoys); } @@ -64,35 +55,6 @@ pub fn insert_ring_member_ids( Ok(()) } -/// Get the ring members for the inputs from the outputs on the chain. -/// -/// Will error if `outputs` does not contain the outputs needed. -pub fn get_ring_members_for_inputs( - get_outputs: impl Fn(u64, u64) -> Option, - inputs: &[Input], -) -> Result>, TransactionError> { - inputs - .iter() - .map(|inp| match inp { - Input::ToKey { - amount, - key_offsets, - .. - } => { - let offsets = get_absolute_offsets(key_offsets)?; - Ok(offsets - .iter() - .map(|offset| { - get_outputs(amount.unwrap_or(0), *offset) - .ok_or(TransactionError::RingMemberNotFoundOrInvalid) - }) - .collect::>()?) - } - _ => Err(TransactionError::IncorrectInputType), - }) - .collect::>() -} - /// Represents the ring members of all the inputs. #[derive(Debug)] pub enum Rings { @@ -102,45 +64,6 @@ pub enum Rings { RingCT(Vec>), } -impl Rings { - /// Builds the rings for the transaction inputs, from the given outputs. - fn new( - outputs: Vec>, - tx_version: TxVersion, - ) -> Result { - Ok(match tx_version { - TxVersion::RingSignatures => Rings::Legacy( - outputs - .into_iter() - .map(|inp_outs| { - inp_outs - .into_iter() - .map(|out| out.key.ok_or(TransactionError::RingMemberNotFoundOrInvalid)) - .collect::, TransactionError>>() - }) - .collect::, TransactionError>>()?, - ), - TxVersion::RingCT => Rings::RingCT( - outputs - .into_iter() - .map(|inp_outs| { - inp_outs - .into_iter() - .map(|out| { - Ok([ - out.key - .ok_or(TransactionError::RingMemberNotFoundOrInvalid)?, - out.commitment, - ]) - }) - .collect::>() - }) - .collect::>()?, - ), - }) - } -} - /// Information on the outputs the transaction is referencing for inputs (ring members). #[derive(Debug)] pub struct TxRingMembersInfo { @@ -151,46 +74,6 @@ pub struct TxRingMembersInfo { pub time_locked_outs: Vec, } -impl TxRingMembersInfo { - /// Construct a [`TxRingMembersInfo`] struct. - /// - /// The used outs must be all the ring members used in the transactions inputs. - pub fn new( - used_outs: Vec>, - decoy_info: Option, - tx_version: TxVersion, - ) -> Result { - Ok(TxRingMembersInfo { - youngest_used_out_height: used_outs - .iter() - .map(|inp_outs| { - inp_outs - .iter() - // the output with the highest height is the youngest - .map(|out| out.height) - .max() - .expect("Input must have ring members") - }) - .max() - .expect("Tx must have inputs"), - time_locked_outs: used_outs - .iter() - .flat_map(|inp_outs| { - inp_outs - .iter() - .filter_map(|out| match out.time_lock { - Timelock::None => None, - lock => Some(lock), - }) - .collect::>() - }) - .collect(), - rings: Rings::new(used_outs, tx_version)?, - decoy_info, - }) - } -} - /// A struct holding information about the inputs and their decoys. This data can vary by block so /// this data needs to be retrieved after every change in the blockchain. /// diff --git a/consensus/src/context/difficulty.rs b/consensus/src/context/difficulty.rs index c7accc9d..0e5447de 100644 --- a/consensus/src/context/difficulty.rs +++ b/consensus/src/context/difficulty.rs @@ -12,8 +12,9 @@ use tower::ServiceExt; use tracing::instrument; use cuprate_helper::num::median; +use cuprate_types::service::{BCReadRequest, BCResponse}; -use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork}; +use crate::{Database, ExtendedConsensusError, HardFork}; /// The amount of blocks we account for to calculate difficulty const DIFFICULTY_WINDOW: usize = 720; @@ -301,8 +302,8 @@ async fn get_blocks_in_pow_info( ) -> Result<(VecDeque, VecDeque), ExtendedConsensusError> { tracing::info!("Getting blocks timestamps"); - let DatabaseResponse::BlockExtendedHeaderInRange(ext_header) = database - .oneshot(DatabaseRequest::BlockExtendedHeaderInRange(block_heights)) + let BCResponse::BlockExtendedHeaderInRange(ext_header) = database + .oneshot(BCReadRequest::BlockExtendedHeaderInRange(block_heights)) .await? else { panic!("Database sent incorrect response"); diff --git a/consensus/src/context/hardforks.rs b/consensus/src/context/hardforks.rs index ea5a72d6..fe9cd7f1 100644 --- a/consensus/src/context/hardforks.rs +++ b/consensus/src/context/hardforks.rs @@ -4,8 +4,9 @@ use tower::ServiceExt; use tracing::instrument; use cuprate_consensus_rules::{HFVotes, HFsInfo, HardFork}; +use cuprate_types::service::{BCReadRequest, BCResponse}; -use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError}; +use crate::{Database, ExtendedConsensusError}; /// The default amount of hard-fork votes to track to decide on activation of a hard-fork. /// @@ -86,16 +87,17 @@ impl HardForkState { debug_assert_eq!(votes.total_votes(), config.window) } - let DatabaseResponse::BlockExtendedHeader(ext_header) = database + let BCResponse::BlockExtendedHeader(ext_header) = database .ready() .await? - .call(DatabaseRequest::BlockExtendedHeader(chain_height - 1)) + .call(BCReadRequest::BlockExtendedHeader(chain_height - 1)) .await? else { panic!("Database sent incorrect response!"); }; - let current_hardfork = ext_header.version; + let current_hardfork = + HardFork::from_version(ext_header.version).expect("Stored block has invalid hardfork"); let mut hfs = HardForkState { config, @@ -165,15 +167,15 @@ async fn get_votes_in_range( ) -> Result { let mut votes = HFVotes::new(window_size); - let DatabaseResponse::BlockExtendedHeaderInRange(vote_list) = database - .oneshot(DatabaseRequest::BlockExtendedHeaderInRange(block_heights)) + let BCResponse::BlockExtendedHeaderInRange(vote_list) = database + .oneshot(BCReadRequest::BlockExtendedHeaderInRange(block_heights)) .await? else { panic!("Database sent incorrect response!"); }; for hf_info in vote_list.into_iter() { - votes.add_vote_for_hf(&hf_info.vote); + votes.add_vote_for_hf(&HardFork::from_vote(hf_info.vote)); } Ok(votes) diff --git a/consensus/src/context/rx_vms.rs b/consensus/src/context/rx_vms.rs index d91c74ec..ba9b6a4d 100644 --- a/consensus/src/context/rx_vms.rs +++ b/consensus/src/context/rx_vms.rs @@ -20,8 +20,9 @@ use cuprate_consensus_rules::{ HardFork, }; use cuprate_helper::asynch::rayon_spawn_async; +use cuprate_types::service::{BCReadRequest, BCResponse}; -use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError}; +use crate::{Database, ExtendedConsensusError}; /// The amount of randomX VMs to keep in the cache. const RX_SEEDS_CACHED: usize = 2; @@ -225,10 +226,8 @@ async fn get_block_hashes( for height in heights { let db = database.clone(); fut.push_back(async move { - let DatabaseResponse::BlockHash(hash) = db - .clone() - .oneshot(DatabaseRequest::BlockHash(height)) - .await? + let BCResponse::BlockHash(hash) = + db.clone().oneshot(BCReadRequest::BlockHash(height)).await? else { panic!("Database sent incorrect response!"); }; diff --git a/consensus/src/context/task.rs b/consensus/src/context/task.rs index 39654bea..286bd619 100644 --- a/consensus/src/context/task.rs +++ b/consensus/src/context/task.rs @@ -9,13 +9,14 @@ use tower::ServiceExt; use tracing::Instrument; use cuprate_consensus_rules::blocks::ContextToVerifyBlock; +use cuprate_types::service::{BCReadRequest, BCResponse}; use super::{ difficulty, hardforks, rx_vms, weight, BlockChainContext, BlockChainContextRequest, BlockChainContextResponse, ContextConfig, RawBlockChainContext, ValidityToken, BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW, }; -use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError}; +use crate::{Database, ExtendedConsensusError}; /// A request from the context service to the context task. pub(super) struct ContextTaskRequest { @@ -69,19 +70,19 @@ impl ContextTask { tracing::debug!("Initialising blockchain context"); - let DatabaseResponse::ChainHeight(chain_height, top_block_hash) = database + let BCResponse::ChainHeight(chain_height, top_block_hash) = database .ready() .await? - .call(DatabaseRequest::ChainHeight) + .call(BCReadRequest::ChainHeight) .await? else { panic!("Database sent incorrect response!"); }; - let DatabaseResponse::GeneratedCoins(already_generated_coins) = database + let BCResponse::GeneratedCoins(already_generated_coins) = database .ready() .await? - .call(DatabaseRequest::GeneratedCoins) + .call(BCReadRequest::GeneratedCoins) .await? else { panic!("Database sent incorrect response!"); diff --git a/consensus/src/context/weight.rs b/consensus/src/context/weight.rs index 9636ddbd..26a6e11e 100644 --- a/consensus/src/context/weight.rs +++ b/consensus/src/context/weight.rs @@ -18,8 +18,9 @@ use tracing::instrument; use cuprate_consensus_rules::blocks::{penalty_free_zone, PENALTY_FREE_ZONE_5}; use cuprate_helper::{asynch::rayon_spawn_async, num::median}; +use cuprate_types::service::{BCReadRequest, BCResponse}; -use crate::{Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, HardFork}; +use crate::{Database, ExtendedConsensusError, HardFork}; /// The short term block weight window. const SHORT_TERM_WINDOW: u64 = 100; @@ -292,8 +293,8 @@ async fn get_blocks_weight_in_range( ) -> Result, ExtendedConsensusError> { tracing::info!("getting block weights."); - let DatabaseResponse::BlockExtendedHeaderInRange(ext_headers) = database - .oneshot(DatabaseRequest::BlockExtendedHeaderInRange(range)) + let BCResponse::BlockExtendedHeaderInRange(ext_headers) = database + .oneshot(BCReadRequest::BlockExtendedHeaderInRange(range)) .await? else { panic!("Database sent incorrect response!") @@ -313,8 +314,8 @@ async fn get_long_term_weight_in_range( ) -> Result, ExtendedConsensusError> { tracing::info!("getting block long term weights."); - let DatabaseResponse::BlockExtendedHeaderInRange(ext_headers) = database - .oneshot(DatabaseRequest::BlockExtendedHeaderInRange(range)) + let BCResponse::BlockExtendedHeaderInRange(ext_headers) = database + .oneshot(BCReadRequest::BlockExtendedHeaderInRange(range)) .await? else { panic!("Database sent incorrect response!") diff --git a/consensus/src/lib.rs b/consensus/src/lib.rs index c91a7809..7088aa9e 100644 --- a/consensus/src/lib.rs +++ b/consensus/src/lib.rs @@ -10,12 +10,7 @@ //! implement a database you need to have a service which accepts [`DatabaseRequest`] and responds //! with [`DatabaseResponse`]. //! -use std::{ - collections::{HashMap, HashSet}, - future::Future, -}; - -use cuprate_consensus_rules::{transactions::OutputOnChain, ConsensusError, HardFork}; +use cuprate_consensus_rules::{ConsensusError, HardFork}; mod batch_verifier; pub mod block; @@ -34,6 +29,9 @@ pub use context::{ }; pub use transactions::{TxVerifierService, VerifyTxRequest, VerifyTxResponse}; +// re-export. +pub use cuprate_types::service::{BCReadRequest, BCResponse}; + /// An Error returned from one of the consensus services. #[derive(Debug, thiserror::Error)] pub enum ExtendedConsensusError { @@ -80,115 +78,36 @@ where Ok((block_svc, tx_svc)) } -/// An internal trait used to represent a database so we don't have to write [`tower::Service`] bounds -/// everywhere. -pub trait Database: - tower::Service< - DatabaseRequest, - Response = DatabaseResponse, - Error = tower::BoxError, - Future = Self::Future2, -> -{ - type Future2: Future> + Send + 'static; -} +use __private::Database; -impl> - Database for T -where - T::Future: Future> + Send + 'static, -{ - type Future2 = T::Future; -} +pub mod __private { + use std::future::Future; -/// An extended block header. -#[derive(Debug, Copy, Clone)] -pub struct ExtendedBlockHeader { - /// The blocks major version. - pub version: HardFork, - /// The blocks vote. - pub vote: HardFork, + use cuprate_types::service::{BCReadRequest, BCResponse}; - /// The blocks timestamp. - pub timestamp: u64, - /// The blocks cumulative difficulty. - pub cumulative_difficulty: u128, - - /// The blocks weight. - pub block_weight: usize, - /// The blocks long term weight. - pub long_term_weight: usize, -} - -/// A database request to the database [`tower::Service`] -#[derive(Debug, Clone)] -pub enum DatabaseRequest { - /// A block extended header request. - /// Must return: [`DatabaseResponse::BlockExtendedHeader`] - BlockExtendedHeader(u64), - /// A block hash request. - /// Must return: [`DatabaseResponse::BlockHash`] - BlockHash(u64), - - /// Removes the block hashes that are not in the _main_ chain. + /// An internal trait used to represent a database so we don't have to write [`tower::Service`] bounds + /// everywhere. /// - /// This should filter (remove) hashes in alt-blocks as well. - FilterUnknownHashes(HashSet<[u8; 32]>), + /// Automatically implemented for: + /// ```ignore + /// tower::Service + /// ``` + pub trait Database: + tower::Service< + BCReadRequest, + Response = BCResponse, + Error = tower::BoxError, + Future = Self::Future2, + > + { + type Future2: Future> + Send + 'static; + } - /// A request for multiple block extended headers. - /// Must return: [`DatabaseResponse::BlockExtendedHeaderInRange`] - BlockExtendedHeaderInRange(std::ops::Range), - - /// A request for the chains height. - /// Must return: [`DatabaseResponse::ChainHeight`] - ChainHeight, - /// A request for the total amount of generated coins. - /// Must return: [`DatabaseResponse::GeneratedCoins`] - GeneratedCoins, - - /// A request for transaction outputs, this contains a map of amounts to amount indexes. - /// Must return: [`DatabaseResponse::Outputs`] - Outputs(HashMap>), - /// A request for the number of outputs with these amounts. - /// Must return: [`DatabaseResponse::NumberOutputsWithAmount`] - NumberOutputsWithAmount(Vec), - - /// A request to check if these key images are in the database. - /// Must return: [`DatabaseResponse::KeyImagesSpent`] - KeyImagesSpent(HashSet<[u8; 32]>), -} - -#[derive(Debug)] -pub enum DatabaseResponse { - /// A block extended header response. - BlockExtendedHeader(ExtendedBlockHeader), - /// A block hash response. - BlockHash([u8; 32]), - - FilteredHashes(HashSet<[u8; 32]>), - - /// A batch block extended header response. - BlockExtendedHeaderInRange(Vec), - - /// A chain height response. - /// Should contains the chains height and top block hash. - ChainHeight(u64, [u8; 32]), - /// Generated coins response. - /// Should contain the total amount of coins emitted in all block rewards. - GeneratedCoins(u64), - - /// Outputs response. - /// Should contain a map of (amounts, amount_idx) -> Output. - /// If an outputs requested does not exist this should *not* be an error, the output - /// should just be omitted from the map. - Outputs(HashMap>), - /// Number of outputs response. - /// Should contain a map of amounts -> numb outs. - /// If there are no outputs with that amount then the numb outs should be zero, *no* amounts - /// requested should be omitted. - NumberOutputsWithAmount(HashMap), - - /// Key images spent response. - /// returns true if key images are spent - KeyImagesSpent(bool), + impl> + crate::Database for T + where + T::Future: Future> + Send + 'static, + { + type Future2 = T::Future; + } } diff --git a/consensus/src/tests/mock_db.rs b/consensus/src/tests/mock_db.rs index d6e86f3a..d3c62910 100644 --- a/consensus/src/tests/mock_db.rs +++ b/consensus/src/tests/mock_db.rs @@ -5,6 +5,10 @@ use std::{ task::{Context, Poll}, }; +use cuprate_types::{ + service::{BCReadRequest, BCResponse}, + ExtendedBlockHeader, +}; use futures::FutureExt; use proptest::{ arbitrary::{any, any_with}, @@ -15,7 +19,7 @@ use proptest::{ use proptest_derive::Arbitrary; use tower::{BoxError, Service}; -use crate::{DatabaseRequest, DatabaseResponse, ExtendedBlockHeader, HardFork}; +use crate::HardFork; prop_compose! { /// Generates an arbitrary full [`DummyDatabase`], it is not safe to do consensus checks on the returned database @@ -56,8 +60,8 @@ pub struct DummyBlockExtendedHeader { impl From for ExtendedBlockHeader { fn from(value: DummyBlockExtendedHeader) -> Self { ExtendedBlockHeader { - version: value.version.unwrap_or(HardFork::V1), - vote: value.vote.unwrap_or(HardFork::V1), + version: value.version.unwrap_or(HardFork::V1) as u8, + vote: value.vote.unwrap_or(HardFork::V1) as u8, timestamp: value.timestamp.unwrap_or_default(), cumulative_difficulty: value.cumulative_difficulty.unwrap_or_default(), block_weight: value.block_weight.unwrap_or_default(), @@ -122,8 +126,8 @@ pub struct DummyDatabase { dummy_height: Option, } -impl Service for DummyDatabase { - type Response = DatabaseResponse; +impl Service for DummyDatabase { + type Response = BCResponse; type Error = BoxError; type Future = Pin> + Send + 'static>>; @@ -132,13 +136,13 @@ impl Service for DummyDatabase { Poll::Ready(Ok(())) } - fn call(&mut self, req: DatabaseRequest) -> Self::Future { + fn call(&mut self, req: BCReadRequest) -> Self::Future { let blocks = self.blocks.clone(); let dummy_height = self.dummy_height; async move { Ok(match req { - DatabaseRequest::BlockExtendedHeader(id) => { + BCReadRequest::BlockExtendedHeader(id) => { let mut id = usize::try_from(id).unwrap(); if let Some(dummy_height) = dummy_height { let block_len = blocks.read().unwrap().len(); @@ -146,7 +150,7 @@ impl Service for DummyDatabase { id -= dummy_height - block_len; } - DatabaseResponse::BlockExtendedHeader( + BCResponse::BlockExtendedHeader( blocks .read() .unwrap() @@ -156,12 +160,12 @@ impl Service for DummyDatabase { .ok_or("block not in database!")?, ) } - DatabaseRequest::BlockHash(id) => { + BCReadRequest::BlockHash(id) => { let mut hash = [0; 32]; hash[0..8].copy_from_slice(&id.to_le_bytes()); - DatabaseResponse::BlockHash(hash) + BCResponse::BlockHash(hash) } - DatabaseRequest::BlockExtendedHeaderInRange(range) => { + BCReadRequest::BlockExtendedHeaderInRange(range) => { let mut end = usize::try_from(range.end).unwrap(); let mut start = usize::try_from(range.start).unwrap(); @@ -172,7 +176,7 @@ impl Service for DummyDatabase { start -= dummy_height - block_len; } - DatabaseResponse::BlockExtendedHeaderInRange( + BCResponse::BlockExtendedHeaderInRange( blocks .read() .unwrap() @@ -184,7 +188,7 @@ impl Service for DummyDatabase { .collect(), ) } - DatabaseRequest::ChainHeight => { + BCReadRequest::ChainHeight => { let height: u64 = dummy_height .unwrap_or(blocks.read().unwrap().len()) .try_into() @@ -193,9 +197,9 @@ impl Service for DummyDatabase { let mut top_hash = [0; 32]; top_hash[0..8].copy_from_slice(&height.to_le_bytes()); - DatabaseResponse::ChainHeight(height, top_hash) + BCResponse::ChainHeight(height, top_hash) } - DatabaseRequest::GeneratedCoins => DatabaseResponse::GeneratedCoins(0), + BCReadRequest::GeneratedCoins => BCResponse::GeneratedCoins(0), _ => unimplemented!("the context svc should not need these requests!"), }) } diff --git a/consensus/src/transactions.rs b/consensus/src/transactions.rs index cf1a9907..65630484 100644 --- a/consensus/src/transactions.rs +++ b/consensus/src/transactions.rs @@ -28,11 +28,12 @@ use cuprate_consensus_rules::{ ConsensusError, HardFork, TxVersion, }; use cuprate_helper::asynch::rayon_spawn_async; +use cuprate_types::service::{BCReadRequest, BCResponse}; use crate::{ batch_verifier::MultiThreadedBatchVerifier, transactions::contextual_data::{batch_get_decoy_info, batch_get_ring_member_info}, - Database, DatabaseRequest, DatabaseResponse, ExtendedConsensusError, + Database, ExtendedConsensusError, }; pub mod contextual_data; @@ -307,10 +308,10 @@ where }) })?; - let DatabaseResponse::KeyImagesSpent(kis_spent) = database + let BCResponse::KeyImagesSpent(kis_spent) = database .ready() .await? - .call(DatabaseRequest::KeyImagesSpent(spent_kis)) + .call(BCReadRequest::KeyImagesSpent(spent_kis)) .await? else { panic!("Database sent incorrect response!"); @@ -339,12 +340,10 @@ where if !verified_at_block_hashes.is_empty() { tracing::trace!("Filtering block hashes not in the main chain."); - let DatabaseResponse::FilteredHashes(known_hashes) = database + let BCResponse::FilterUnknownHashes(known_hashes) = database .ready() .await? - .call(DatabaseRequest::FilterUnknownHashes( - verified_at_block_hashes, - )) + .call(BCReadRequest::FilterUnknownHashes(verified_at_block_hashes)) .await? else { panic!("Database returned wrong response!"); diff --git a/consensus/src/transactions/contextual_data.rs b/consensus/src/transactions/contextual_data.rs index 1cadca17..3a9be32d 100644 --- a/consensus/src/transactions/contextual_data.rs +++ b/consensus/src/transactions/contextual_data.rs @@ -15,21 +15,128 @@ use std::{ sync::Arc, }; -use monero_serai::transaction::Input; +use monero_serai::transaction::{Input, Timelock}; use tower::ServiceExt; use tracing::instrument; +use cuprate_consensus_rules::transactions::Rings; use cuprate_consensus_rules::{ transactions::{ - get_ring_members_for_inputs, insert_ring_member_ids, DecoyInfo, TxRingMembersInfo, + get_absolute_offsets, insert_ring_member_ids, DecoyInfo, TransactionError, + TxRingMembersInfo, }, - ConsensusError, HardFork, + ConsensusError, HardFork, TxVersion, +}; +use cuprate_types::{ + service::{BCReadRequest, BCResponse}, + OutputOnChain, }; -use crate::{ - transactions::TransactionVerificationData, Database, DatabaseRequest, DatabaseResponse, - ExtendedConsensusError, -}; +use crate::{transactions::TransactionVerificationData, Database, ExtendedConsensusError}; + +/// Get the ring members for the inputs from the outputs on the chain. +/// +/// Will error if `outputs` does not contain the outputs needed. +fn get_ring_members_for_inputs( + get_outputs: impl Fn(u64, u64) -> Option, + inputs: &[Input], +) -> Result>, TransactionError> { + inputs + .iter() + .map(|inp| match inp { + Input::ToKey { + amount, + key_offsets, + .. + } => { + let offsets = get_absolute_offsets(key_offsets)?; + Ok(offsets + .iter() + .map(|offset| { + get_outputs(amount.unwrap_or(0), *offset) + .ok_or(TransactionError::RingMemberNotFoundOrInvalid) + }) + .collect::>()?) + } + _ => Err(TransactionError::IncorrectInputType), + }) + .collect::>() +} + +/// Construct a [`TxRingMembersInfo`] struct. +/// +/// The used outs must be all the ring members used in the transactions inputs. +pub fn new_ring_member_info( + used_outs: Vec>, + decoy_info: Option, + tx_version: TxVersion, +) -> Result { + Ok(TxRingMembersInfo { + youngest_used_out_height: used_outs + .iter() + .map(|inp_outs| { + inp_outs + .iter() + // the output with the highest height is the youngest + .map(|out| out.height) + .max() + .expect("Input must have ring members") + }) + .max() + .expect("Tx must have inputs"), + time_locked_outs: used_outs + .iter() + .flat_map(|inp_outs| { + inp_outs + .iter() + .filter_map(|out| match out.time_lock { + Timelock::None => None, + lock => Some(lock), + }) + .collect::>() + }) + .collect(), + rings: new_rings(used_outs, tx_version)?, + decoy_info, + }) +} + +/// Builds the [`Rings`] for the transaction inputs, from the given outputs. +fn new_rings( + outputs: Vec>, + tx_version: TxVersion, +) -> Result { + Ok(match tx_version { + TxVersion::RingSignatures => Rings::Legacy( + outputs + .into_iter() + .map(|inp_outs| { + inp_outs + .into_iter() + .map(|out| out.key.ok_or(TransactionError::RingMemberNotFoundOrInvalid)) + .collect::, TransactionError>>() + }) + .collect::, TransactionError>>()?, + ), + TxVersion::RingCT => Rings::RingCT( + outputs + .into_iter() + .map(|inp_outs| { + inp_outs + .into_iter() + .map(|out| { + Ok([ + out.key + .ok_or(TransactionError::RingMemberNotFoundOrInvalid)?, + out.commitment, + ]) + }) + .collect::>() + }) + .collect::>()?, + ), + }) +} /// Retrieves the [`TxRingMembersInfo`] for the inputted [`TransactionVerificationData`]. /// @@ -47,19 +154,19 @@ pub async fn batch_get_ring_member_info( .map_err(ConsensusError::Transaction)?; } - let DatabaseResponse::Outputs(outputs) = database + let BCResponse::Outputs(outputs) = database .ready() .await? - .call(DatabaseRequest::Outputs(output_ids)) + .call(BCReadRequest::Outputs(output_ids)) .await? else { panic!("Database sent incorrect response!") }; - let DatabaseResponse::NumberOutputsWithAmount(outputs_with_amount) = database + let BCResponse::NumberOutputsWithAmount(outputs_with_amount) = database .ready() .await? - .call(DatabaseRequest::NumberOutputsWithAmount( + .call(BCReadRequest::NumberOutputsWithAmount( outputs.keys().copied().collect(), )) .await? @@ -87,7 +194,7 @@ pub async fn batch_get_ring_member_info( None }; - TxRingMembersInfo::new(ring_members_for_tx, decoy_info, tx_v_data.version) + new_ring_member_info(ring_members_for_tx, decoy_info, tx_v_data.version) .map_err(ConsensusError::Transaction) }) .collect::>()?) @@ -128,10 +235,10 @@ pub async fn batch_get_decoy_info<'a, D: Database + Clone + Send + 'static>( unique_input_amounts.len() ); - let DatabaseResponse::NumberOutputsWithAmount(outputs_with_amount) = database + let BCResponse::NumberOutputsWithAmount(outputs_with_amount) = database .ready() .await? - .call(DatabaseRequest::NumberOutputsWithAmount( + .call(BCReadRequest::NumberOutputsWithAmount( unique_input_amounts.into_iter().collect(), )) .await? diff --git a/consensus/tests/verify_correct_txs.rs b/consensus/tests/verify_correct_txs.rs index 9640d27a..61ba92b8 100644 --- a/consensus/tests/verify_correct_txs.rs +++ b/consensus/tests/verify_correct_txs.rs @@ -4,28 +4,31 @@ use std::{ sync::Arc, }; +use cuprate_types::{ + service::{BCReadRequest, BCResponse}, + OutputOnChain, +}; use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, edwards::CompressedEdwardsY}; use monero_serai::transaction::{Timelock, Transaction}; use tower::{service_fn, Service, ServiceExt}; use cuprate_consensus::{ - Database, DatabaseRequest, DatabaseResponse, TxVerifierService, VerifyTxRequest, - VerifyTxResponse, + TxVerifierService, VerifyTxRequest, VerifyTxResponse, __private::Database, }; -use cuprate_consensus_rules::{transactions::OutputOnChain, HardFork}; +use cuprate_consensus_rules::HardFork; use cuprate_test_utils::data::TX_E2D393; fn dummy_database(outputs: BTreeMap) -> impl Database + Clone { let outputs = Arc::new(outputs); - service_fn(move |req: DatabaseRequest| { + service_fn(move |req: BCReadRequest| { ready(Ok(match req { - DatabaseRequest::NumberOutputsWithAmount(_) => { - DatabaseResponse::NumberOutputsWithAmount(HashMap::new()) + BCReadRequest::NumberOutputsWithAmount(_) => { + BCResponse::NumberOutputsWithAmount(HashMap::new()) } - DatabaseRequest::Outputs(outs) => { + BCReadRequest::Outputs(outs) => { let idxs = outs.get(&0).unwrap(); let mut ret = HashMap::new(); @@ -37,9 +40,9 @@ fn dummy_database(outputs: BTreeMap) -> impl Database + Clon .collect::>(), ); - DatabaseResponse::Outputs(ret) + BCResponse::Outputs(ret) } - DatabaseRequest::KeyImagesSpent(_) => DatabaseResponse::KeyImagesSpent(false), + BCReadRequest::KeyImagesSpent(_) => BCResponse::KeyImagesSpent(false), _ => panic!("Database request not needed for this test"), })) }) diff --git a/storage/cuprate-blockchain/src/service/mod.rs b/storage/cuprate-blockchain/src/service/mod.rs index a95276a7..322edd58 100644 --- a/storage/cuprate-blockchain/src/service/mod.rs +++ b/storage/cuprate-blockchain/src/service/mod.rs @@ -50,11 +50,11 @@ //! This channel can be `.await`ed upon to (eventually) receive //! the corresponding `Response` to your `Request`. //! -//! [req_r]: cuprate_types::service::ReadRequest +//! [req_r]: cuprate_types::service::BCReadRequest //! -//! [req_w]: cuprate_types::service::WriteRequest +//! [req_w]: cuprate_types::service::BCWriteRequest //! -//! [resp]: cuprate_types::service::Response +//! [resp]: cuprate_types::service::BCResponse //! //! # Example //! Simple usage of `service`. @@ -63,7 +63,7 @@ //! use hex_literal::hex; //! use tower::{Service, ServiceExt}; //! -//! use cuprate_types::service::{ReadRequest, WriteRequest, Response}; +//! use cuprate_types::service::{BCReadRequest, BCWriteRequest, BCResponse}; //! use cuprate_test_utils::data::block_v16_tx0; //! //! use cuprate_blockchain::{ConcreteEnv, config::ConfigBuilder, Env}; @@ -82,7 +82,7 @@ //! // Prepare a request to write block. //! let mut block = block_v16_tx0().clone(); //! # block.height = 0 as u64; // must be 0th height or panic in `add_block()` -//! let request = WriteRequest::WriteBlock(block); +//! let request = BCWriteRequest::WriteBlock(block); //! //! // Send the request. //! // We receive back an `async` channel that will @@ -92,16 +92,16 @@ //! //! // Block write was OK. //! let response = response_channel.await?; -//! assert_eq!(response, Response::WriteBlockOk); +//! assert_eq!(response, BCResponse::WriteBlockOk); //! //! // Now, let's try getting the block hash //! // of the block we just wrote. -//! let request = ReadRequest::BlockHash(0); +//! let request = BCReadRequest::BlockHash(0); //! let response_channel = read_handle.ready().await?.call(request); //! let response = response_channel.await?; //! assert_eq!( //! response, -//! Response::BlockHash( +//! BCResponse::BlockHash( //! hex!("43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428") //! ) //! ); diff --git a/storage/cuprate-blockchain/src/service/read.rs b/storage/cuprate-blockchain/src/service/read.rs index e53c7f88..1cfdcdce 100644 --- a/storage/cuprate-blockchain/src/service/read.rs +++ b/storage/cuprate-blockchain/src/service/read.rs @@ -15,7 +15,7 @@ use tokio_util::sync::PollSemaphore; use cuprate_helper::asynch::InfallibleOneshotReceiver; use cuprate_types::{ - service::{ReadRequest, Response}, + service::{BCReadRequest, BCResponse}, ExtendedBlockHeader, OutputOnChain, }; @@ -40,9 +40,9 @@ use crate::{ /// This is cheaply [`Clone`]able handle that /// allows `async`hronously reading from the database. /// -/// Calling [`tower::Service::call`] with a [`DatabaseReadHandle`] & [`ReadRequest`] +/// Calling [`tower::Service::call`] with a [`DatabaseReadHandle`] & [`BCReadRequest`] /// will return an `async`hronous channel that can be `.await`ed upon -/// to receive the corresponding [`Response`]. +/// to receive the corresponding [`BCResponse`]. pub struct DatabaseReadHandle { /// Handle to the custom `rayon` DB reader thread-pool. /// @@ -131,8 +131,8 @@ impl DatabaseReadHandle { } } -impl tower::Service for DatabaseReadHandle { - type Response = Response; +impl tower::Service for DatabaseReadHandle { + type Response = BCResponse; type Error = RuntimeError; type Future = ResponseReceiver; @@ -152,7 +152,7 @@ impl tower::Service for DatabaseReadHandle { } #[inline] - fn call(&mut self, request: ReadRequest) -> Self::Future { + fn call(&mut self, request: BCReadRequest) -> Self::Future { let permit = self .permit .take() @@ -189,13 +189,13 @@ impl tower::Service for DatabaseReadHandle { /// The basic structure is: /// 1. `Request` is mapped to a handler function /// 2. Handler function is called -/// 3. [`Response`] is sent +/// 3. [`BCResponse`] is sent fn map_request( env: &ConcreteEnv, // Access to the database - request: ReadRequest, // The request we must fulfill + request: BCReadRequest, // The request we must fulfill response_sender: ResponseSender, // The channel we must send the response back to ) { - use ReadRequest as R; + use BCReadRequest as R; /* SOMEDAY: pre-request handling, run some code for each request? */ @@ -286,7 +286,7 @@ macro_rules! get_tables { // FIXME: implement multi-transaction read atomicity. // . -/// [`ReadRequest::BlockExtendedHeader`]. +/// [`BCReadRequest::BlockExtendedHeader`]. #[inline] fn block_extended_header(env: &ConcreteEnv, block_height: BlockHeight) -> ResponseResult { // Single-threaded, no `ThreadLocal` required. @@ -294,12 +294,12 @@ fn block_extended_header(env: &ConcreteEnv, block_height: BlockHeight) -> Respon let tx_ro = env_inner.tx_ro()?; let tables = env_inner.open_tables(&tx_ro)?; - Ok(Response::BlockExtendedHeader( + Ok(BCResponse::BlockExtendedHeader( get_block_extended_header_from_height(&block_height, &tables)?, )) } -/// [`ReadRequest::BlockHash`]. +/// [`BCReadRequest::BlockHash`]. #[inline] fn block_hash(env: &ConcreteEnv, block_height: BlockHeight) -> ResponseResult { // Single-threaded, no `ThreadLocal` required. @@ -307,12 +307,12 @@ fn block_hash(env: &ConcreteEnv, block_height: BlockHeight) -> ResponseResult { let tx_ro = env_inner.tx_ro()?; let table_block_infos = env_inner.open_db_ro::(&tx_ro)?; - Ok(Response::BlockHash( + Ok(BCResponse::BlockHash( get_block_info(&block_height, &table_block_infos)?.block_hash, )) } -/// [`ReadRequest::BlockExtendedHeaderInRange`]. +/// [`BCReadRequest::BlockExtendedHeaderInRange`]. #[inline] fn block_extended_header_in_range( env: &ConcreteEnv, @@ -333,10 +333,10 @@ fn block_extended_header_in_range( }) .collect::, RuntimeError>>()?; - Ok(Response::BlockExtendedHeaderInRange(vec)) + Ok(BCResponse::BlockExtendedHeaderInRange(vec)) } -/// [`ReadRequest::ChainHeight`]. +/// [`BCReadRequest::ChainHeight`]. #[inline] fn chain_height(env: &ConcreteEnv) -> ResponseResult { // Single-threaded, no `ThreadLocal` required. @@ -349,10 +349,10 @@ fn chain_height(env: &ConcreteEnv) -> ResponseResult { let block_hash = get_block_info(&chain_height.saturating_sub(1), &table_block_infos)?.block_hash; - Ok(Response::ChainHeight(chain_height, block_hash)) + Ok(BCResponse::ChainHeight(chain_height, block_hash)) } -/// [`ReadRequest::GeneratedCoins`]. +/// [`BCReadRequest::GeneratedCoins`]. #[inline] fn generated_coins(env: &ConcreteEnv) -> ResponseResult { // Single-threaded, no `ThreadLocal` required. @@ -363,13 +363,13 @@ fn generated_coins(env: &ConcreteEnv) -> ResponseResult { let top_height = top_block_height(&table_block_heights)?; - Ok(Response::GeneratedCoins(cumulative_generated_coins( + Ok(BCResponse::GeneratedCoins(cumulative_generated_coins( &top_height, &table_block_infos, )?)) } -/// [`ReadRequest::Outputs`]. +/// [`BCReadRequest::Outputs`]. #[inline] fn outputs(env: &ConcreteEnv, outputs: HashMap>) -> ResponseResult { // Prepare tx/tables in `ThreadLocal`. @@ -407,10 +407,10 @@ fn outputs(env: &ConcreteEnv, outputs: HashMap>) -> }) .collect::>, RuntimeError>>()?; - Ok(Response::Outputs(map)) + Ok(BCResponse::Outputs(map)) } -/// [`ReadRequest::NumberOutputsWithAmount`]. +/// [`BCReadRequest::NumberOutputsWithAmount`]. #[inline] fn number_outputs_with_amount(env: &ConcreteEnv, amounts: Vec) -> ResponseResult { // Prepare tx/tables in `ThreadLocal`. @@ -452,10 +452,10 @@ fn number_outputs_with_amount(env: &ConcreteEnv, amounts: Vec) -> Respon }) .collect::, RuntimeError>>()?; - Ok(Response::NumberOutputsWithAmount(map)) + Ok(BCResponse::NumberOutputsWithAmount(map)) } -/// [`ReadRequest::CheckKIsNotSpent`]. +/// [`BCReadRequest::CheckKIsNotSpent`]. #[inline] fn check_k_is_not_spent(env: &ConcreteEnv, key_images: HashSet) -> ResponseResult { // Prepare tx/tables in `ThreadLocal`. @@ -486,8 +486,8 @@ fn check_k_is_not_spent(env: &ConcreteEnv, key_images: HashSet) -> Res // Else, `Ok(false)` will continue the iterator. .find_any(|result| !matches!(result, Ok(false))) { - None | Some(Ok(false)) => Ok(Response::CheckKIsNotSpent(true)), // Key image was NOT found. - Some(Ok(true)) => Ok(Response::CheckKIsNotSpent(false)), // Key image was found. + None | Some(Ok(false)) => Ok(BCResponse::CheckKIsNotSpent(true)), // Key image was NOT found. + Some(Ok(true)) => Ok(BCResponse::CheckKIsNotSpent(false)), // Key image was found. Some(Err(e)) => Err(e), // A database error occurred. } } diff --git a/storage/cuprate-blockchain/src/service/tests.rs b/storage/cuprate-blockchain/src/service/tests.rs index 77c10cdd..d8705496 100644 --- a/storage/cuprate-blockchain/src/service/tests.rs +++ b/storage/cuprate-blockchain/src/service/tests.rs @@ -16,7 +16,7 @@ use tower::{Service, ServiceExt}; use cuprate_test_utils::data::{block_v16_tx0, block_v1_tx2, block_v9_tx3}; use cuprate_types::{ - service::{ReadRequest, Response, WriteRequest}, + service::{BCReadRequest, BCResponse, BCWriteRequest}, OutputOnChain, VerifiedBlockInformation, }; @@ -81,10 +81,10 @@ async fn test_template( block.height = i as u64; // Request a block to be written, assert it was written. - let request = WriteRequest::WriteBlock(block); + let request = BCWriteRequest::WriteBlock(block); let response_channel = writer.call(request); let response = response_channel.await.unwrap(); - assert_eq!(response, Response::WriteBlockOk); + assert_eq!(response, BCResponse::WriteBlockOk); } //----------------------------------------------------------------------- Reset the transaction @@ -100,36 +100,36 @@ async fn test_template( // Next few lines are just for preparing the expected responses, // see further below for usage. - let extended_block_header_0 = Ok(Response::BlockExtendedHeader( + let extended_block_header_0 = Ok(BCResponse::BlockExtendedHeader( get_block_extended_header_from_height(&0, &tables).unwrap(), )); let extended_block_header_1 = if block_fns.len() > 1 { - Ok(Response::BlockExtendedHeader( + Ok(BCResponse::BlockExtendedHeader( get_block_extended_header_from_height(&1, &tables).unwrap(), )) } else { Err(RuntimeError::KeyNotFound) }; - let block_hash_0 = Ok(Response::BlockHash( + let block_hash_0 = Ok(BCResponse::BlockHash( get_block_info(&0, tables.block_infos()).unwrap().block_hash, )); let block_hash_1 = if block_fns.len() > 1 { - Ok(Response::BlockHash( + Ok(BCResponse::BlockHash( get_block_info(&1, tables.block_infos()).unwrap().block_hash, )) } else { Err(RuntimeError::KeyNotFound) }; - let range_0_1 = Ok(Response::BlockExtendedHeaderInRange(vec![ + let range_0_1 = Ok(BCResponse::BlockExtendedHeaderInRange(vec![ get_block_extended_header_from_height(&0, &tables).unwrap(), ])); let range_0_2 = if block_fns.len() >= 2 { - Ok(Response::BlockExtendedHeaderInRange(vec![ + Ok(BCResponse::BlockExtendedHeaderInRange(vec![ get_block_extended_header_from_height(&0, &tables).unwrap(), get_block_extended_header_from_height(&1, &tables).unwrap(), ])) @@ -140,10 +140,10 @@ async fn test_template( let chain_height = { let height = chain_height(tables.block_heights()).unwrap(); let block_info = get_block_info(&height.saturating_sub(1), tables.block_infos()).unwrap(); - Ok(Response::ChainHeight(height, block_info.block_hash)) + Ok(BCResponse::ChainHeight(height, block_info.block_hash)) }; - let cumulative_generated_coins = Ok(Response::GeneratedCoins(cumulative_generated_coins)); + let cumulative_generated_coins = Ok(BCResponse::GeneratedCoins(cumulative_generated_coins)); let num_req = tables .outputs_iter() @@ -153,7 +153,7 @@ async fn test_template( .map(|key| key.amount) .collect::>(); - let num_resp = Ok(Response::NumberOutputsWithAmount( + let num_resp = Ok(BCResponse::NumberOutputsWithAmount( num_req .iter() .map(|amount| match tables.num_outputs().get(amount) { @@ -168,21 +168,27 @@ async fn test_template( // Contains a fake non-spent key-image. let ki_req = HashSet::from([[0; 32]]); - let ki_resp = Ok(Response::CheckKIsNotSpent(true)); + let ki_resp = Ok(BCResponse::CheckKIsNotSpent(true)); //----------------------------------------------------------------------- Assert expected response // Assert read requests lead to the expected responses. for (request, expected_response) in [ - (ReadRequest::BlockExtendedHeader(0), extended_block_header_0), - (ReadRequest::BlockExtendedHeader(1), extended_block_header_1), - (ReadRequest::BlockHash(0), block_hash_0), - (ReadRequest::BlockHash(1), block_hash_1), - (ReadRequest::BlockExtendedHeaderInRange(0..1), range_0_1), - (ReadRequest::BlockExtendedHeaderInRange(0..2), range_0_2), - (ReadRequest::ChainHeight, chain_height), - (ReadRequest::GeneratedCoins, cumulative_generated_coins), - (ReadRequest::NumberOutputsWithAmount(num_req), num_resp), - (ReadRequest::CheckKIsNotSpent(ki_req), ki_resp), + ( + BCReadRequest::BlockExtendedHeader(0), + extended_block_header_0, + ), + ( + BCReadRequest::BlockExtendedHeader(1), + extended_block_header_1, + ), + (BCReadRequest::BlockHash(0), block_hash_0), + (BCReadRequest::BlockHash(1), block_hash_1), + (BCReadRequest::BlockExtendedHeaderInRange(0..1), range_0_1), + (BCReadRequest::BlockExtendedHeaderInRange(0..2), range_0_2), + (BCReadRequest::ChainHeight, chain_height), + (BCReadRequest::GeneratedCoins, cumulative_generated_coins), + (BCReadRequest::NumberOutputsWithAmount(num_req), num_resp), + (BCReadRequest::CheckKIsNotSpent(ki_req), ki_resp), ] { let response = reader.clone().oneshot(request).await; println!("response: {response:#?}, expected_response: {expected_response:#?}"); @@ -196,10 +202,10 @@ async fn test_template( // Assert each key image we inserted comes back as "spent". for key_image in tables.key_images_iter().keys().unwrap() { let key_image = key_image.unwrap(); - let request = ReadRequest::CheckKIsNotSpent(HashSet::from([key_image])); + let request = BCReadRequest::CheckKIsNotSpent(HashSet::from([key_image])); let response = reader.clone().oneshot(request).await; println!("response: {response:#?}, key_image: {key_image:#?}"); - assert_eq!(response.unwrap(), Response::CheckKIsNotSpent(false)); + assert_eq!(response.unwrap(), BCResponse::CheckKIsNotSpent(false)); } //----------------------------------------------------------------------- Output checks @@ -260,10 +266,10 @@ async fn test_template( .collect::>(); // Send a request for every output we inserted before. - let request = ReadRequest::Outputs(map.clone()); + let request = BCReadRequest::Outputs(map.clone()); let response = reader.clone().oneshot(request).await; println!("Response::Outputs response: {response:#?}"); - let Ok(Response::Outputs(response)) = response else { + let Ok(BCResponse::Outputs(response)) = response else { panic!("{response:#?}") }; diff --git a/storage/cuprate-blockchain/src/service/types.rs b/storage/cuprate-blockchain/src/service/types.rs index 265bf42c..53e3270e 100644 --- a/storage/cuprate-blockchain/src/service/types.rs +++ b/storage/cuprate-blockchain/src/service/types.rs @@ -6,15 +6,15 @@ use futures::channel::oneshot::Sender; use cuprate_helper::asynch::InfallibleOneshotReceiver; -use cuprate_types::service::Response; +use cuprate_types::service::BCResponse; use crate::error::RuntimeError; //---------------------------------------------------------------------------------------------------- Types /// The actual type of the response. /// -/// Either our [`Response`], or a database error occurred. -pub(super) type ResponseResult = Result; +/// Either our [`BCResponse`], or a database error occurred. +pub(super) type ResponseResult = Result; /// The `Receiver` channel that receives the read response. /// diff --git a/storage/cuprate-blockchain/src/service/write.rs b/storage/cuprate-blockchain/src/service/write.rs index d6747e97..edc1b609 100644 --- a/storage/cuprate-blockchain/src/service/write.rs +++ b/storage/cuprate-blockchain/src/service/write.rs @@ -10,7 +10,7 @@ use futures::channel::oneshot; use cuprate_helper::asynch::InfallibleOneshotReceiver; use cuprate_types::{ - service::{Response, WriteRequest}, + service::{BCResponse, BCWriteRequest}, VerifiedBlockInformation, }; @@ -33,15 +33,15 @@ const WRITER_THREAD_NAME: &str = concat!(module_path!(), "::DatabaseWriter"); /// it is not [`Clone`]able as there is only ever 1 place within Cuprate /// that writes. /// -/// Calling [`tower::Service::call`] with a [`DatabaseWriteHandle`] & [`WriteRequest`] +/// Calling [`tower::Service::call`] with a [`DatabaseWriteHandle`] & [`BCWriteRequest`] /// will return an `async`hronous channel that can be `.await`ed upon -/// to receive the corresponding [`Response`]. +/// to receive the corresponding [`BCResponse`]. #[derive(Debug)] pub struct DatabaseWriteHandle { /// Sender channel to the database write thread-pool. /// /// We provide the response channel for the thread-pool. - pub(super) sender: crossbeam::channel::Sender<(WriteRequest, ResponseSender)>, + pub(super) sender: crossbeam::channel::Sender<(BCWriteRequest, ResponseSender)>, } impl DatabaseWriteHandle { @@ -65,8 +65,8 @@ impl DatabaseWriteHandle { } } -impl tower::Service for DatabaseWriteHandle { - type Response = Response; +impl tower::Service for DatabaseWriteHandle { + type Response = BCResponse; type Error = RuntimeError; type Future = ResponseReceiver; @@ -76,7 +76,7 @@ impl tower::Service for DatabaseWriteHandle { } #[inline] - fn call(&mut self, request: WriteRequest) -> Self::Future { + fn call(&mut self, request: BCWriteRequest) -> Self::Future { // Response channel we `.await` on. let (response_sender, receiver) = oneshot::channel(); @@ -95,7 +95,7 @@ pub(super) struct DatabaseWriter { /// Any caller can send some requests to this channel. /// They send them alongside another `Response` channel, /// which we will eventually send to. - receiver: crossbeam::channel::Receiver<(WriteRequest, ResponseSender)>, + receiver: crossbeam::channel::Receiver<(BCWriteRequest, ResponseSender)>, /// Access to the database. env: Arc, @@ -153,7 +153,7 @@ impl DatabaseWriter { // FIXME: will there be more than 1 write request? // this won't have to be an enum. let response = match &request { - WriteRequest::WriteBlock(block) => write_block(&self.env, block), + BCWriteRequest::WriteBlock(block) => write_block(&self.env, block), }; // If the database needs to resize, do so. @@ -218,7 +218,7 @@ impl DatabaseWriter { // Each function will return the [`Response`] that we // should send back to the caller in [`map_request()`]. -/// [`WriteRequest::WriteBlock`]. +/// [`BCWriteRequest::WriteBlock`]. #[inline] fn write_block(env: &ConcreteEnv, block: &VerifiedBlockInformation) -> ResponseResult { let env_inner = env.env_inner(); @@ -232,7 +232,7 @@ fn write_block(env: &ConcreteEnv, block: &VerifiedBlockInformation) -> ResponseR match result { Ok(()) => { TxRw::commit(tx_rw)?; - Ok(Response::WriteBlockOk) + Ok(BCResponse::WriteBlockOk) } Err(e) => { // INVARIANT: ensure database atomicity by aborting diff --git a/types/Cargo.toml b/types/Cargo.toml index 8e69e8fb..a8b4344a 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -13,10 +13,7 @@ default = ["service"] service = [] [dependencies] -borsh = { workspace = true, optional = true } -cfg-if = { workspace = true } curve25519-dalek = { workspace = true } monero-serai = { workspace = true } -serde = { workspace = true, optional = true } [dev-dependencies] \ No newline at end of file diff --git a/types/src/lib.rs b/types/src/lib.rs index 8c077901..d6410da5 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -92,10 +92,7 @@ pub use types::{ }; //---------------------------------------------------------------------------------------------------- Feature-gated -cfg_if::cfg_if! { - if #[cfg(feature = "service")] { - pub mod service; - } -} +#[cfg(feature = "service")] +pub mod service; //---------------------------------------------------------------------------------------------------- Private diff --git a/types/src/service.rs b/types/src/service.rs index 078c8464..79960ecc 100644 --- a/types/src/service.rs +++ b/types/src/service.rs @@ -1,10 +1,7 @@ -//! Database [`ReadRequest`]s, [`WriteRequest`]s, and [`Response`]s. -//! -//! See [`cuprate_database`](https://github.com/Cuprate/cuprate/blob/00c3692eac6b2669e74cfd8c9b41c7e704c779ad/database/src/service/mod.rs#L1-L59)'s -//! `service` module for more usage/documentation. +//! Database [`BCReadRequest`]s, [`BCWriteRequest`]s, and [`BCResponse`]s. //! //! Tests that assert particular requests lead to particular -//! responses are also tested in `cuprate_database`. +//! responses are also tested in Cuprate's blockchain database crate. //---------------------------------------------------------------------------------------------------- Import use std::{ @@ -20,18 +17,16 @@ use serde::{Deserialize, Serialize}; use crate::types::{ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}; //---------------------------------------------------------------------------------------------------- ReadRequest -/// A read request to the database. +/// A read request to the blockchain database. /// -/// This pairs with [`Response`], where each variant here -/// matches in name with a `Response` variant. For example, -/// the proper response for a [`ReadRequest::BlockHash`] -/// would be a [`Response::BlockHash`]. +/// This pairs with [`BCResponse`], where each variant here +/// matches in name with a [`BCResponse`] variant. For example, +/// the proper response for a [`BCReadRequest::BlockHash`] +/// would be a [`BCResponse::BlockHash`]. /// /// See `Response` for the expected responses per `Request`. #[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] -pub enum ReadRequest { +pub enum BCReadRequest { /// Request a block's extended header. /// /// The input is the block's height. @@ -42,6 +37,11 @@ pub enum ReadRequest { /// The input is the block's height. BlockHash(u64), + /// Removes the block hashes that are not in the _main_ chain. + /// + /// This should filter (remove) hashes in alt-blocks as well. + FilterUnknownHashes(HashSet<[u8; 32]>), + /// Request a range of block extended headers. /// /// The input is a range of block heights. @@ -86,18 +86,17 @@ pub enum ReadRequest { /// Check that all key images within a set arer not spent. /// /// Input is a set of key images. - CheckKIsNotSpent(HashSet<[u8; 32]>), + KeyImagesSpent(HashSet<[u8; 32]>), } //---------------------------------------------------------------------------------------------------- WriteRequest -/// A write request to the database. +/// A write request to the blockchain database. /// /// There is currently only 1 write request to the database, -/// as such, the only valid [`Response`] to this request is -/// the proper response for a [`Response::WriteBlockOk`]. +/// as such, the only valid [`BCResponse`] to this request is +/// the proper response for a [`BCResponse::WriteBlockOk`]. #[derive(Debug, Clone, PartialEq, Eq)] -// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] -pub enum WriteRequest { +pub enum BCWriteRequest { /// Request that a block be written to the database. /// /// Input is an already verified block. @@ -109,60 +108,64 @@ pub enum WriteRequest { /// /// These are the data types returned when using sending a `Request`. /// -/// This pairs with [`ReadRequest`] and [`WriteRequest`], +/// This pairs with [`BCReadRequest`] and [`BCWriteRequest`], /// see those two for more info. #[derive(Debug, Clone, PartialEq, Eq)] -// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] -pub enum Response { +pub enum BCResponse { //------------------------------------------------------ Reads - /// Response to [`ReadRequest::BlockExtendedHeader`]. + /// Response to [`BCReadRequest::BlockExtendedHeader`]. /// /// Inner value is the extended headed of the requested block. BlockExtendedHeader(ExtendedBlockHeader), - /// Response to [`ReadRequest::BlockHash`]. + /// Response to [`BCReadRequest::BlockHash`]. /// /// Inner value is the hash of the requested block. BlockHash([u8; 32]), - /// Response to [`ReadRequest::BlockExtendedHeaderInRange`]. + /// Response tp [`BCReadRequest::FilterUnknownHashes`]. + /// + /// Inner value is the list of hashes that were in the main chain. + FilterUnknownHashes(HashSet<[u8; 32]>), + + /// Response to [`BCReadRequest::BlockExtendedHeaderInRange`]. /// /// Inner value is the list of extended header(s) of the requested block(s). BlockExtendedHeaderInRange(Vec), - /// Response to [`ReadRequest::ChainHeight`]. + /// Response to [`BCReadRequest::ChainHeight`]. /// /// Inner value is the chain height, and the top block's hash. ChainHeight(u64, [u8; 32]), - /// Response to [`ReadRequest::GeneratedCoins`]. + /// Response to [`BCReadRequest::GeneratedCoins`]. /// /// Inner value is the total amount of generated coins so far, in atomic units. GeneratedCoins(u64), - /// Response to [`ReadRequest::Outputs`]. + /// Response to [`BCReadRequest::Outputs`]. /// /// Inner value is all the outputs requested, /// associated with their amount and amount index. Outputs(HashMap>), - /// Response to [`ReadRequest::NumberOutputsWithAmount`]. + /// Response to [`BCReadRequest::NumberOutputsWithAmount`]. /// /// Inner value is a `HashMap` of all the outputs requested where: /// - Key = output amount /// - Value = count of outputs with the same amount NumberOutputsWithAmount(HashMap), - /// Response to [`ReadRequest::CheckKIsNotSpent`]. + /// Response to [`BCReadRequest::KeyImagesSpent`]. /// /// The inner value is `true` if _any_ of the key images - /// were spent (exited in the database already). + /// were spent (existed in the database already). /// /// The inner value is `false` if _none_ of the key images were spent. - CheckKIsNotSpent(bool), + KeyImagesSpent(bool), //------------------------------------------------------ Writes - /// Response to [`WriteRequest::WriteBlock`]. + /// Response to [`BCWriteRequest::WriteBlock`]. /// /// This response indicates that the requested block has /// successfully been written to the database without error. diff --git a/types/src/types.rs b/types/src/types.rs index aeef4535..a7a2efdd 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -21,8 +21,6 @@ use serde::{Deserialize, Serialize}; /// /// For more definitions, see also: . #[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] pub struct ExtendedBlockHeader { /// The block's major version. /// @@ -52,8 +50,6 @@ pub struct ExtendedBlockHeader { /// This represents data that allows verification of a transaction, /// although it doesn't mean it _has_ been verified. #[derive(Clone, Debug, PartialEq, Eq)] -// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] // FIXME: monero_serai -// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] pub struct TransactionVerificationData { /// The transaction itself. pub tx: Transaction, @@ -111,9 +107,7 @@ pub struct VerifiedBlockInformation { //---------------------------------------------------------------------------------------------------- OutputOnChain /// An already existing transaction output. -#[derive(Clone, Debug, PartialEq, Eq)] -// #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] // FIXME: monero_serai -// #[cfg_attr(feature = "borsh", derive(BorshSerialize, BorshDeserialize))] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct OutputOnChain { /// The block height this output belongs to. pub height: u64,