Update to experimental monero oxide api ()

* add specific method for context

* add new statemachine for tx verification

* fix consensus crates build

* working builds

* fix CI

* add docs

* fix CI

* fix docs

* fix clippy

* cleanup

* add docs to `blockchain_context`

* fix doc tests

* add output cache

* new monero-serai

* todo

* todo

* Revert "new monero-serai"

This reverts commit fe3f6acc67.

* use indexmap to request outputs

* clean up

* fix typos

* fix CI

* fix cargo hack

* fix reorgs

* check if a block is already present before adding it to the alt block cache

* fmt

* update to new monero oxide API

* fmt & fix cache

* update config values

* fix tests

* fix no-std builds
This commit is contained in:
Boog900 2025-03-06 19:03:25 +00:00 committed by GitHub
parent 2dc258e4c8
commit 5c2b56c78e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 113 additions and 114 deletions
Cargo.lockCargo.toml
binaries/cuprated
config
src
blockchain/manager
config
consensus
helper/src
storage
blockchain/src/ops
txpool/src/ops
types/src

30
Cargo.lock generated
View file

@ -1152,7 +1152,7 @@ dependencies = [
[[package]]
name = "dalek-ff-group"
version = "0.4.1"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"crypto-bigint",
"curve25519-dalek",
@ -1317,7 +1317,7 @@ dependencies = [
[[package]]
name = "flexible-transcript"
version = "0.3.2"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"blake2",
"digest",
@ -2023,7 +2023,7 @@ dependencies = [
[[package]]
name = "monero-address"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"monero-io",
@ -2036,7 +2036,7 @@ dependencies = [
[[package]]
name = "monero-borromean"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"monero-generators",
@ -2049,7 +2049,7 @@ dependencies = [
[[package]]
name = "monero-bulletproofs"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"monero-generators",
@ -2064,7 +2064,7 @@ dependencies = [
[[package]]
name = "monero-clsag"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"dalek-ff-group",
@ -2084,7 +2084,7 @@ dependencies = [
[[package]]
name = "monero-generators"
version = "0.4.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"dalek-ff-group",
@ -2098,7 +2098,7 @@ dependencies = [
[[package]]
name = "monero-io"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"std-shims",
@ -2107,7 +2107,7 @@ dependencies = [
[[package]]
name = "monero-mlsag"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"monero-generators",
@ -2121,7 +2121,7 @@ dependencies = [
[[package]]
name = "monero-primitives"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"monero-generators",
@ -2134,7 +2134,7 @@ dependencies = [
[[package]]
name = "monero-rpc"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"hex",
@ -2150,7 +2150,7 @@ dependencies = [
[[package]]
name = "monero-serai"
version = "0.1.4-alpha"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"curve25519-dalek",
"hex-literal",
@ -2168,7 +2168,7 @@ dependencies = [
[[package]]
name = "monero-simple-request-rpc"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"digest_auth",
"hex",
@ -2865,7 +2865,7 @@ dependencies = [
[[package]]
name = "simple-request"
version = "0.1.0"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"http-body-util",
"hyper",
@ -2931,7 +2931,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "std-shims"
version = "0.1.1"
source = "git+https://github.com/Cuprate/serai.git?rev=e6fdef6#e6fdef6d0b4481932ac9647796eb3fa56197ed66"
source = "git+https://github.com/Cuprate/serai.git?rev=e6ae8c2#e6ae8c2b1f9d791f35ea225032cc0a3f79dec99d"
dependencies = [
"hashbrown 0.14.5",
"spin",

View file

@ -121,7 +121,7 @@ futures = { version = "0.3", default-features = false }
hex = { version = "0.4", default-features = false }
hex-literal = { version = "0.4", default-features = false }
indexmap = { version = "2", default-features = false }
monero-serai = { git = "https://github.com/Cuprate/serai.git", rev = "e6fdef6", default-features = false }
monero-serai = { git = "https://github.com/Cuprate/serai.git", rev = "e6ae8c2", default-features = false }
nu-ansi-term = { version = "0.46", default-features = false }
paste = { version = "1", default-features = false }
pin-project = { version = "1", default-features = false }
@ -145,8 +145,8 @@ tracing-subscriber = { version = "0.3", default-features = false }
tracing = { version = "0.1", default-features = false }
## workspace.dev-dependencies
monero-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "e6fdef6" }
monero-simple-request-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "e6fdef6" }
monero-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "e6ae8c2" }
monero-simple-request-rpc = { git = "https://github.com/Cuprate/serai.git", rev = "e6ae8c2" }
tempfile = { version = "3" }
pretty_assertions = { version = "1" }
proptest = { version = "1" }

View file

@ -43,9 +43,9 @@ peer_save_period = { secs = 90, nanos = 0 }
## The block downloader config.
[p2p.block_downloader]
## The size of the buffer of sequential blocks waiting to be verified and added to the chain (bytes).
buffer_bytes = 50_000_000
buffer_bytes = 1_000_000_000
## The size of the queue of blocks which are waiting for a parent block to be downloaded (bytes).
in_progress_queue_bytes = 50_000_000
in_progress_queue_bytes = 500_000_000
## The target size of a batch of blocks (bytes), must not exceed 100MB.
target_batch_bytes = 10_000_000
## The amount of time between checking the pool of connected peers for free peers to download blocks.

View file

@ -452,7 +452,7 @@ impl super::BlockchainManager {
.iter()
.flat_map(|tx| {
tx.tx.prefix().inputs.iter().map(|input| match input {
Input::ToKey { key_image, .. } => key_image.compress().0,
Input::ToKey { key_image, .. } => key_image.0,
Input::Gen(_) => unreachable!(),
})
})

View file

@ -47,8 +47,8 @@ impl From<BlockDownloaderConfig> for cuprate_p2p::block_downloader::BlockDownloa
impl Default for BlockDownloaderConfig {
fn default() -> Self {
Self {
buffer_bytes: 50_000_000,
in_progress_queue_bytes: 50_000_000,
buffer_bytes: 1_000_000_000,
in_progress_queue_bytes: 500_000_000,
check_client_pool_interval: Duration::from_secs(30),
target_batch_bytes: 10_000_000,
}

View file

@ -1,17 +1,20 @@
use std::cmp::Ordering;
use curve25519_dalek::EdwardsPoint;
use monero_serai::{
io::decompress_point,
ringct::RctType,
transaction::{Input, Output, Timelock, Transaction},
};
pub use cuprate_types::TxVersion;
use crate::{
batch_verifier::BatchVerifier, blocks::penalty_free_zone, check_point_canonically_encoded,
is_decomposed_amount, HardFork,
};
// re-export.
pub use cuprate_types::TxVersion;
mod contextual_data;
mod ring_ct;
mod ring_signatures;
@ -327,7 +330,10 @@ fn check_key_images(input: &Input) -> Result<(), TransactionError> {
match input {
Input::ToKey { key_image, .. } => {
// this happens in monero-serai but we may as well duplicate the check.
if !key_image.is_torsion_free() {
if !decompress_point(*key_image)
.as_ref()
.is_some_and(EdwardsPoint::is_torsion_free)
{
return Err(TransactionError::KeyImageIsNotInPrimeSubGroup);
}
}
@ -388,7 +394,7 @@ fn check_ring_members_unique(input: &Input, hf: HardFork) -> Result<(), Transact
/// ref: <https://monero-book.cuprate.org/consensus_rules/transactions/inputs.html#sorted-inputs>
fn check_inputs_sorted(inputs: &[Input], hf: HardFork) -> Result<(), TransactionError> {
let get_ki = |inp: &Input| match inp {
Input::ToKey { key_image, .. } => Ok(key_image.compress().to_bytes()),
Input::ToKey { key_image, .. } => Ok(key_image.to_bytes()),
Input::Gen(_) => Err(TransactionError::IncorrectInputType),
};

View file

@ -1,6 +1,6 @@
use std::cmp::{max, min};
use curve25519_dalek::EdwardsPoint;
use curve25519_dalek::edwards::CompressedEdwardsY;
use indexmap::{IndexMap, IndexSet};
use monero_serai::transaction::{Input, Timelock};
@ -57,9 +57,9 @@ pub fn insert_ring_member_ids(
#[derive(Debug)]
pub enum Rings {
/// Legacy, pre-ringCT, rings.
Legacy(Vec<Vec<EdwardsPoint>>),
Legacy(Vec<Vec<CompressedEdwardsY>>),
/// `RingCT` rings, (outkey, amount commitment).
RingCT(Vec<Vec<[EdwardsPoint; 2]>>),
RingCT(Vec<Vec<[CompressedEdwardsY; 2]>>),
}
/// Information on the outputs the transaction is referencing for inputs (ring members).

View file

@ -2,6 +2,7 @@ use curve25519_dalek::{EdwardsPoint, Scalar};
use hex_literal::hex;
use monero_serai::{
generators::H,
io::decompress_point,
ringct::{
clsag::ClsagError,
mlsag::{AggregateRingMatrixBuilder, MlsagError, RingMatrix},
@ -74,9 +75,21 @@ fn simple_type_balances(rct_sig: &RctProofs) -> Result<(), RingCTError> {
}
};
let sum_inputs = pseudo_outs.iter().sum::<EdwardsPoint>();
let sum_outputs =
rct_sig.base.commitments.iter().sum::<EdwardsPoint>() + Scalar::from(rct_sig.base.fee) * *H;
let sum_inputs = pseudo_outs
.iter()
.copied()
.map(decompress_point)
.sum::<Option<EdwardsPoint>>()
.ok_or(RingCTError::SimpleAmountDoNotBalance)?;
let sum_outputs = rct_sig
.base
.commitments
.iter()
.copied()
.map(decompress_point)
.sum::<Option<EdwardsPoint>>()
.ok_or(RingCTError::SimpleAmountDoNotBalance)?
+ Scalar::from(rct_sig.base.fee) * *H;
if sum_inputs == sum_outputs {
Ok(())
@ -178,7 +191,7 @@ pub(crate) fn check_input_signatures(
.collect::<Vec<_>>();
let mut matrix =
AggregateRingMatrixBuilder::new(&proofs.base.commitments, proofs.base.fee);
AggregateRingMatrixBuilder::new(&proofs.base.commitments, proofs.base.fee)?;
rings.iter().try_for_each(|ring| matrix.push_ring(ring))?;
@ -210,7 +223,7 @@ pub(crate) fn check_input_signatures(
panic!("How did we build a ring with no decoys?");
};
Ok(clsags.verify(ring, key_image, pseudo_out, msg)?)
Ok(clsags.verify(ring.clone(), key_image, pseudo_out, msg)?)
}),
}
}

View file

@ -1,7 +1,7 @@
use std::ops::Range;
use curve25519_dalek::{
constants::{ED25519_BASEPOINT_POINT, EIGHT_TORSION},
constants::{ED25519_BASEPOINT_COMPRESSED, EIGHT_TORSION},
edwards::CompressedEdwardsY,
EdwardsPoint,
};
@ -92,7 +92,7 @@ fn test_decoy_info() {
fn test_torsion_ki() {
for &key_image in &EIGHT_TORSION[1..] {
assert!(check_key_images(&Input::ToKey {
key_image,
key_image: key_image.compress(),
amount: None,
key_offsets: vec![],
})
@ -262,13 +262,13 @@ proptest! {
#[test]
fn test_check_input_has_decoys(key_offsets in vec(any::<u64>(), 1..10_000)) {
assert!(check_input_has_decoys(&Input::ToKey {
key_image: ED25519_BASEPOINT_POINT,
key_image: ED25519_BASEPOINT_COMPRESSED,
amount: None,
key_offsets,
}).is_ok());
assert!(check_input_has_decoys(&Input::ToKey {
key_image: ED25519_BASEPOINT_POINT,
key_image: ED25519_BASEPOINT_COMPRESSED,
amount: None,
key_offsets: vec![],
}).is_err());

View file

@ -289,7 +289,7 @@ pub(crate) async fn check_kis_unique<D: Database>(
txs.try_for_each(|tx| {
tx.tx.prefix().inputs.iter().try_for_each(|input| {
if let Input::ToKey { key_image, .. } = input {
if !spent_kis.insert(key_image.compress().0) {
if !spent_kis.insert(key_image.0) {
tracing::debug!("Duplicate key image found in batch.");
return Err(ConsensusError::Transaction(TransactionError::KeyImageSpent));
}

View file

@ -96,27 +96,19 @@ pub fn new_ring_member_info(
.collect::<Vec<_>>()
})
.collect(),
rings: new_rings(used_outs, tx_version)?,
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<Vec<OutputOnChain>>,
tx_version: TxVersion,
) -> Result<Rings, TransactionError> {
Ok(match tx_version {
fn new_rings(outputs: Vec<Vec<OutputOnChain>>, tx_version: TxVersion) -> Rings {
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::<Result<Vec<_>, TransactionError>>()
})
.collect::<Result<Vec<_>, TransactionError>>()?,
.map(|inp_outs| inp_outs.into_iter().map(|out| out.key).collect::<Vec<_>>())
.collect::<Vec<_>>(),
),
TxVersion::RingCT => Rings::RingCT(
outputs
@ -124,18 +116,12 @@ fn new_rings(
.map(|inp_outs| {
inp_outs
.into_iter()
.map(|out| {
Ok([
out.key
.ok_or(TransactionError::RingMemberNotFoundOrInvalid)?,
out.commitment,
])
})
.collect::<Result<_, TransactionError>>()
.map(|out| [out.key, out.commitment])
.collect::<_>()
})
.collect::<Result<_, _>>()?,
.collect::<_>(),
),
})
}
}
/// Retrieves an [`OutputCache`] for the list of transactions.
@ -158,7 +144,7 @@ pub async fn get_output_cache<D: Database>(
.call(BlockchainReadRequest::Outputs(output_ids))
.await?
else {
panic!("Database sent incorrect response!")
unreachable!();
};
Ok(outputs)

View file

@ -7,7 +7,7 @@ use std::{
sync::Arc,
};
use curve25519_dalek::{constants::ED25519_BASEPOINT_POINT, edwards::CompressedEdwardsY};
use curve25519_dalek::{constants::ED25519_BASEPOINT_COMPRESSED, edwards::CompressedEdwardsY};
use indexmap::IndexMap;
use monero_serai::transaction::{Timelock, Transaction};
use tower::service_fn;
@ -71,13 +71,8 @@ macro_rules! test_verify_valid_v2_tx {
OutputOnChain {
height: 0,
time_lock: Timelock::None,
commitment: CompressedEdwardsY::from_slice(&hex_literal::hex!($commitment))
.unwrap()
.decompress()
.unwrap(),
key: CompressedEdwardsY::from_slice(&hex_literal::hex!($ring_member))
.unwrap()
.decompress(),
commitment: CompressedEdwardsY(hex_literal::hex!($commitment)),
key: CompressedEdwardsY(hex_literal::hex!($ring_member)),
}),)+)+
];
@ -103,10 +98,8 @@ macro_rules! test_verify_valid_v2_tx {
OutputOnChain {
height: 0,
time_lock: Timelock::None,
commitment: ED25519_BASEPOINT_POINT,
key: CompressedEdwardsY::from_slice(&hex_literal::hex!($ring_member))
.unwrap()
.decompress(),
commitment: ED25519_BASEPOINT_COMPRESSED,
key: CompressedEdwardsY(hex_literal::hex!($ring_member)),
}),)+)+
];

View file

@ -4,8 +4,11 @@
use std::sync::LazyLock;
use curve25519_dalek::{
constants::ED25519_BASEPOINT_POINT, edwards::VartimeEdwardsPrecomputation,
traits::VartimePrecomputedMultiscalarMul, EdwardsPoint, Scalar,
constants::{ED25519_BASEPOINT_COMPRESSED, ED25519_BASEPOINT_POINT},
edwards::CompressedEdwardsY,
edwards::VartimeEdwardsPrecomputation,
traits::VartimePrecomputedMultiscalarMul,
Scalar,
};
use monero_serai::generators::H;
@ -49,15 +52,16 @@ static H_PRECOMP: LazyLock<VartimeEdwardsPrecomputation> =
/// # Invariant
/// This function assumes that the [`ZERO_COMMITMENT_DECOMPOSED_AMOUNT`]
/// table is sorted.
pub static ZERO_COMMITMENT_LOOKUP_TABLE: LazyLock<[EdwardsPoint; 172]> = LazyLock::new(|| {
let mut lookup_table: [EdwardsPoint; 172] = [ED25519_BASEPOINT_POINT; 172];
pub static ZERO_COMMITMENT_LOOKUP_TABLE: LazyLock<[CompressedEdwardsY; 172]> =
LazyLock::new(|| {
let mut lookup_table: [CompressedEdwardsY; 172] = [ED25519_BASEPOINT_COMPRESSED; 172];
for (i, amount) in ZERO_COMMITMENT_DECOMPOSED_AMOUNT.into_iter().enumerate() {
lookup_table[i] = ED25519_BASEPOINT_POINT + *H * Scalar::from(amount);
}
for (i, amount) in ZERO_COMMITMENT_DECOMPOSED_AMOUNT.into_iter().enumerate() {
lookup_table[i] = (ED25519_BASEPOINT_POINT + *H * Scalar::from(amount)).compress();
}
lookup_table
});
lookup_table
});
//---------------------------------------------------------------------------------------------------- Free functions
@ -66,7 +70,7 @@ pub static ZERO_COMMITMENT_LOOKUP_TABLE: LazyLock<[EdwardsPoint; 172]> = LazyLoc
/// It will first attempt to lookup into the table of known Pre-RCT value.
/// Compute it otherwise.
#[expect(clippy::cast_possible_truncation)]
pub fn compute_zero_commitment(amount: u64) -> EdwardsPoint {
pub fn compute_zero_commitment(amount: u64) -> CompressedEdwardsY {
// OPTIMIZATION: Unlike monerod which execute a linear search across its lookup
// table (O(n)). Cuprate is making use of an arithmetic based constant time
// version (O(1)). It has been benchmarked in both hit and miss scenarios against
@ -78,7 +82,7 @@ pub fn compute_zero_commitment(amount: u64) -> EdwardsPoint {
// the amount without its most significant digit.
let Some(log) = amount.checked_ilog10() else {
// amount = 0 so H component is 0.
return ED25519_BASEPOINT_POINT;
return ED25519_BASEPOINT_COMPRESSED;
};
let div = 10_u64.pow(log);
@ -89,7 +93,9 @@ pub fn compute_zero_commitment(amount: u64) -> EdwardsPoint {
// there aren't only trailing zeroes behind the most significant digit.
// The amount is not part of the table and can calculated apart.
if most_significant_digit * div != amount {
return H_PRECOMP.vartime_multiscalar_mul([Scalar::from(amount), Scalar::ONE]);
return H_PRECOMP
.vartime_multiscalar_mul([Scalar::from(amount), Scalar::ONE])
.compress();
}
// Calculating the index back by progressing within the powers of 10.
@ -116,7 +122,10 @@ mod test {
fn compare_lookup_with_computation() {
for amount in ZERO_COMMITMENT_DECOMPOSED_AMOUNT {
let commitment = H_PRECOMP.vartime_multiscalar_mul([Scalar::from(amount), Scalar::ONE]);
assert!(commitment == compute_zero_commitment(amount));
assert_eq!(
commitment,
compute_zero_commitment(amount).decompress().unwrap()
);
}
}
}

View file

@ -35,7 +35,7 @@ pub fn tx_fee(tx: &Transaction) -> u64 {
#[cfg(test)]
mod test {
use curve25519_dalek::{edwards::CompressedEdwardsY, EdwardsPoint};
use curve25519_dalek::edwards::CompressedEdwardsY;
use monero_serai::transaction::{NotPruned, Output, Timelock, TransactionPrefix};
use super::*;
@ -46,7 +46,7 @@ mod test {
let input = Input::ToKey {
amount: Some(u64::MAX),
key_offsets: vec![],
key_image: EdwardsPoint::default(),
key_image: CompressedEdwardsY::default(),
};
let output = Output {

View file

@ -165,9 +165,7 @@ pub fn output_to_output_on_chain(
Timelock::None
};
let key = CompressedEdwardsY::from_slice(&output.key)
.map(|y| y.decompress())
.unwrap_or(None);
let key = CompressedEdwardsY(output.key);
Ok(OutputOnChain {
height: output.height as usize,
@ -191,10 +189,7 @@ pub fn rct_output_to_output_on_chain(
table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
) -> DbResult<OutputOnChain> {
// INVARIANT: Commitments stored are valid when stored by the database.
let commitment = CompressedEdwardsY::from_slice(&rct_output.commitment)
.unwrap()
.decompress()
.unwrap();
let commitment = CompressedEdwardsY(rct_output.commitment);
let time_lock = if rct_output
.output_flags
@ -205,9 +200,7 @@ pub fn rct_output_to_output_on_chain(
Timelock::None
};
let key = CompressedEdwardsY::from_slice(&rct_output.key)
.map(|y| y.decompress())
.unwrap_or(None);
let key = CompressedEdwardsY(rct_output.key);
Ok(OutputOnChain {
height: rct_output.height as usize,

View file

@ -96,7 +96,7 @@ pub fn add_tx(
match inputs {
// Key images.
Input::ToKey { key_image, .. } => {
add_key_image(key_image.compress().as_bytes(), tables.key_images_mut())?;
add_key_image(key_image.as_bytes(), tables.key_images_mut())?;
}
// This is a miner transaction, set it for later use.
Input::Gen(_) => miner_tx = true,
@ -154,7 +154,7 @@ pub fn add_tx(
height,
output_flags,
tx_idx: tx_id,
commitment: commitment.compress().0,
commitment: commitment.0,
},
tables.rct_outputs_mut(),
)
@ -219,7 +219,7 @@ pub fn remove_tx(tx_hash: &TxHash, tables: &mut impl TablesMut) -> DbResult<(TxI
match inputs {
// Key images.
Input::ToKey { key_image, .. } => {
remove_key_image(key_image.compress().as_bytes(), tables.key_images_mut())?;
remove_key_image(key_image.as_bytes(), tables.key_images_mut())?;
}
// This is a miner transaction, set it for later use.
Input::Gen(_) => miner_tx = true,

View file

@ -48,7 +48,7 @@ pub(super) fn remove_tx_key_images(
/// This function will panic if the [`Input`] is not [`Input::ToKey`]
fn ki_from_input(input: &Input) -> [u8; 32] {
match input {
Input::ToKey { key_image, .. } => key_image.compress().0,
Input::ToKey { key_image, .. } => key_image.0,
Input::Gen(_) => panic!("miner tx cannot be added to the txpool"),
}
}

View file

@ -71,7 +71,7 @@ impl From<transaction::Transaction> for Transaction {
let key = Key {
amount: amount.unwrap_or(0),
key_offsets,
k_image: HexBytes::<32>(key_image.compress().0),
k_image: HexBytes::<32>(key_image.0),
};
Some(Input { key })
@ -169,7 +169,7 @@ impl From<transaction::Transaction> for Transaction {
.base
.commitments
.into_iter()
.map(|point| HexBytes::<32>(point.compress().0))
.map(|point| HexBytes::<32>(point.0))
.collect();
let rct_signatures = RctSignatures::NonCoinbase {

View file

@ -1,4 +1,4 @@
use curve25519_dalek::EdwardsPoint;
use curve25519_dalek::edwards::CompressedEdwardsY;
use indexmap::{IndexMap, IndexSet};
use monero_serai::transaction::Transaction;
@ -87,8 +87,7 @@ impl OutputCache {
OutputOnChain {
height,
time_lock: tx.prefix().additional_timelock,
// TODO: this needs to check the point is canonical.
key: out.key.decompress(),
key: out.key,
commitment: get_output_commitment(tx, i),
},
);
@ -111,7 +110,7 @@ impl OutputCache {
}
/// Returns the amount commitment for the output at the given index `i` in the [`Transaction`]
fn get_output_commitment(tx: &Transaction, i: usize) -> EdwardsPoint {
fn get_output_commitment(tx: &Transaction, i: usize) -> CompressedEdwardsY {
match tx {
Transaction::V1 { prefix, .. } => {
compute_zero_commitment(prefix.outputs[i].amount.unwrap_or_default())

View file

@ -2,7 +2,7 @@
use std::num::NonZero;
use curve25519_dalek::edwards::EdwardsPoint;
use curve25519_dalek::edwards::CompressedEdwardsY;
use monero_serai::{
block::Block,
transaction::{Timelock, Transaction},
@ -142,9 +142,9 @@ pub struct OutputOnChain {
/// The timelock of this output, if any.
pub time_lock: Timelock,
/// The public key of this output, if any.
pub key: Option<EdwardsPoint>,
pub key: CompressedEdwardsY,
/// The output's commitment.
pub commitment: EdwardsPoint,
pub commitment: CompressedEdwardsY,
}
/// Input required to generate an output histogram.