Skip to content

Commit 8959b8e

Browse files
author
SyntheticBird45
committed
Applied edits
1 parent 6a2afa7 commit 8959b8e

File tree

10 files changed

+122
-273
lines changed

10 files changed

+122
-273
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

constants/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ default = []
1313
block = []
1414
build = []
1515
rpc = []
16-
crypto = []
1716

1817
[dependencies]
1918

constants/src/crypto.rs

Lines changed: 0 additions & 184 deletions
This file was deleted.

constants/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,5 @@ mod macros;
88
pub mod block;
99
#[cfg(feature = "build")]
1010
pub mod build;
11-
#[cfg(feature = "crypto")]
12-
pub mod crypto;
1311
#[cfg(feature = "rpc")]
1412
pub mod rpc;

helper/Cargo.toml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus"
1010

1111
[features]
1212
# All features off by default.
13-
default = []
13+
default = ["std"]
1414
std = []
1515
atomic = ["dep:crossbeam"]
1616
asynch = ["dep:futures", "dep:rayon"]
1717
cast = []
1818
constants = []
19+
crypto = ["dep:curve25519-dalek", "dep:monero-serai"]
1920
fs = ["dep:dirs"]
2021
num = []
2122
map = ["cast", "dep:monero-serai", "dep:cuprate-constants"]
@@ -26,12 +27,13 @@ tx = ["dep:monero-serai"]
2627
[dependencies]
2728
cuprate-constants = { path = "../constants", optional = true, features = ["block"] }
2829

29-
crossbeam = { workspace = true, optional = true }
30-
chrono = { workspace = true, optional = true, features = ["std", "clock"] }
31-
dirs = { workspace = true, optional = true }
32-
futures = { workspace = true, optional = true, features = ["std"] }
33-
monero-serai = { workspace = true, optional = true }
34-
rayon = { workspace = true, optional = true }
30+
chrono = { workspace = true, optional = true, features = ["std", "clock"] }
31+
crossbeam = { workspace = true, optional = true }
32+
curve25519-dalek = { workspace = true, optional = true }
33+
dirs = { workspace = true, optional = true }
34+
futures = { workspace = true, optional = true, features = ["std"] }
35+
monero-serai = { workspace = true, optional = true }
36+
rayon = { workspace = true, optional = true }
3537

3638
# This is kinda a stupid work around.
3739
# [thread] needs to activate one of these libs (windows|libc)

helper/src/crypto.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//! Crypto related functions and runtime initialized constants
2+
3+
//---------------------------------------------------------------------------------------------------- Use
4+
use std::sync::LazyLock;
5+
6+
use curve25519_dalek::{
7+
constants::ED25519_BASEPOINT_POINT, edwards::VartimeEdwardsPrecomputation,
8+
traits::VartimePrecomputedMultiscalarMul, EdwardsPoint, Scalar,
9+
};
10+
use monero_serai::generators::H;
11+
12+
/// This is the decomposed amount table containing the mandatory Pre-RCT amounts. It is use to pre-compute
13+
/// zero commitments at runtime.
14+
///
15+
/// Defined at:
16+
/// - <https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/ringct/rctOps.cpp#L44>
17+
#[rustfmt::skip]
18+
const ZERO_COMMITMENT_DECOMPOSED_AMOUNT: [u64; 172] = [
19+
1, 2, 3, 4, 5, 6, 7, 8, 9,
20+
10, 20, 30, 40, 50, 60, 70, 80, 90,
21+
100, 200, 300, 400, 500, 600, 700, 800, 900,
22+
1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000,
23+
10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000,
24+
100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000,
25+
1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000,
26+
10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000,
27+
100000000, 200000000, 300000000, 400000000, 500000000, 600000000, 700000000, 800000000, 900000000,
28+
1000000000, 2000000000, 3000000000, 4000000000, 5000000000, 6000000000, 7000000000, 8000000000, 9000000000,
29+
10000000000, 20000000000, 30000000000, 40000000000, 50000000000, 60000000000, 70000000000, 80000000000, 90000000000,
30+
100000000000, 200000000000, 300000000000, 400000000000, 500000000000, 600000000000, 700000000000, 800000000000, 900000000000,
31+
1000000000000, 2000000000000, 3000000000000, 4000000000000, 5000000000000, 6000000000000, 7000000000000, 8000000000000, 9000000000000,
32+
10000000000000, 20000000000000, 30000000000000, 40000000000000, 50000000000000, 60000000000000, 70000000000000, 80000000000000, 90000000000000,
33+
100000000000000, 200000000000000, 300000000000000, 400000000000000, 500000000000000, 600000000000000, 700000000000000, 800000000000000, 900000000000000,
34+
1000000000000000, 2000000000000000, 3000000000000000, 4000000000000000, 5000000000000000, 6000000000000000, 7000000000000000, 8000000000000000, 9000000000000000,
35+
10000000000000000, 20000000000000000, 30000000000000000, 40000000000000000, 50000000000000000, 60000000000000000, 70000000000000000, 80000000000000000, 90000000000000000,
36+
100000000000000000, 200000000000000000, 300000000000000000, 400000000000000000, 500000000000000000, 600000000000000000, 700000000000000000, 800000000000000000, 900000000000000000,
37+
1000000000000000000, 2000000000000000000, 3000000000000000000, 4000000000000000000, 5000000000000000000, 6000000000000000000, 7000000000000000000, 8000000000000000000, 9000000000000000000,
38+
10000000000000000000
39+
];
40+
41+
/// Runtime initialized H generator.
42+
static H_PRECOMP: LazyLock<VartimeEdwardsPrecomputation> =
43+
LazyLock::new(|| VartimeEdwardsPrecomputation::new([*H, ED25519_BASEPOINT_POINT]));
44+
45+
/// Runtime initialized zero commitment lookup table
46+
///
47+
/// ASSUMPTION: This function assume that the [`ZERO_COMMITMENT_DECOMPOSED_AMOUNT`]
48+
/// table is sorted.
49+
pub static ZERO_COMMITMENT_LOOKUP_TABLE: LazyLock<[(u64, EdwardsPoint); 172]> =
50+
LazyLock::new(|| {
51+
let mut lookup_table: [(u64, EdwardsPoint); 172] = [(0_u64, ED25519_BASEPOINT_POINT); 172];
52+
53+
for (i, amount) in ZERO_COMMITMENT_DECOMPOSED_AMOUNT.into_iter().enumerate() {
54+
lookup_table[i] = (
55+
amount,
56+
(ED25519_BASEPOINT_POINT + *H * Scalar::from(amount)),
57+
);
58+
}
59+
60+
lookup_table
61+
});
62+
63+
/// This function compute the zero commitment given a specific amount.
64+
///
65+
/// It will first attempt to lookup into the table of known Pre-RCT value.
66+
/// Compute it otherwise.
67+
pub fn compute_zero_commitments(amount: u64) -> EdwardsPoint {
68+
// OPTIMIZATION: We first make an arithmetic check that the value lies between valid pre-computed amounts. This permit to avoid the lookup cost if possible
69+
if amount > 10 && amount % 10 != 0 {
70+
return H_PRECOMP.vartime_multiscalar_mul([Scalar::from(amount), Scalar::from(1_u8)]);
71+
}
72+
73+
// Binary search in lookup table (O(log2(n)) instead of O(n))
74+
let (mut start, mut end, mut c): (usize, usize, Option<EdwardsPoint>) =
75+
(0, (ZERO_COMMITMENT_LOOKUP_TABLE.len() - 1) / 2, None);
76+
while start <= end {
77+
let mid = (start + end) / 2;
78+
let lookup = ZERO_COMMITMENT_LOOKUP_TABLE[mid].0;
79+
match amount {
80+
a if a == lookup => {
81+
c = Some(ZERO_COMMITMENT_LOOKUP_TABLE[mid].1);
82+
}
83+
a if a < lookup => {
84+
end = mid - 1;
85+
}
86+
_ => {
87+
start = mid + 1;
88+
}
89+
}
90+
}
91+
92+
// Compute the zero commitment if not found.
93+
c.unwrap_or_else(|| {
94+
H_PRECOMP.vartime_multiscalar_mul([Scalar::from(amount), Scalar::from(1_u8)])
95+
})
96+
}

helper/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ pub mod time;
3030

3131
#[cfg(feature = "tx")]
3232
pub mod tx;
33+
34+
#[cfg(all(feature = "crypto", feature = "std"))]
35+
pub mod crypto;
3336
//---------------------------------------------------------------------------------------------------- Private Usage
3437

3538
//----------------------------------------------------------------------------------------------------

storage/blockchain/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ redb-memory = ["cuprate-database/redb-memory"]
1818
service = ["dep:thread_local", "dep:rayon", "cuprate-helper/thread"]
1919

2020
[dependencies]
21-
cuprate-constants = { path = "../../constants", features = ["crypto"]}
2221
cuprate-database = { path = "../database" }
2322
cuprate-database-service = { path = "../service" }
24-
cuprate-helper = { path = "../../helper", features = ["fs", "map"] }
23+
cuprate-helper = { path = "../../helper", features = ["fs", "map", "crypto"] }
2524
cuprate-types = { path = "../../types", features = ["blockchain"] }
2625
cuprate-pruning = { path = "../../pruning" }
2726

storage/blockchain/src/ops/output.rs

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
//! Output functions.
22
33
//---------------------------------------------------------------------------------------------------- Import
4-
use curve25519_dalek::{
5-
constants::ED25519_BASEPOINT_POINT, edwards::CompressedEdwardsY, EdwardsPoint, Scalar,
6-
};
7-
use monero_serai::{generators::H, transaction::Timelock};
4+
use curve25519_dalek::edwards::CompressedEdwardsY;
5+
use monero_serai::transaction::Timelock;
86

9-
use cuprate_constants::crypto::ZERO_COMMITMENT_LOOKUP_TABLE as ZC_LT;
107
use cuprate_database::{
118
RuntimeError, {DatabaseRo, DatabaseRw},
129
};
10+
use cuprate_helper::crypto::compute_zero_commitments;
1311
use cuprate_helper::map::u64_to_timelock;
1412
use cuprate_types::OutputOnChain;
1513

@@ -158,31 +156,7 @@ pub fn output_to_output_on_chain(
158156
amount: Amount,
159157
table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
160158
) -> Result<OutputOnChain, RuntimeError> {
161-
// Binary search in lookup table (O(log2(n)+2) instead of O(n+2))
162-
let commitment: EdwardsPoint = {
163-
let (mut start, mut end, mut c): (usize, usize, Option<EdwardsPoint>) =
164-
(0, (ZC_LT.len() - 1) / 2, None);
165-
while start <= end {
166-
let mid = (start + end) / 2;
167-
let lookup = ZC_LT[mid].0;
168-
match amount {
169-
a if a == lookup => {
170-
c = CompressedEdwardsY::from_slice(&ZC_LT[mid].1)
171-
.expect("The lookup table cannot contain invalid curve point data")
172-
.decompress();
173-
}
174-
a if a < lookup => {
175-
end = mid - 1;
176-
}
177-
_ => {
178-
start = mid + 1;
179-
}
180-
}
181-
}
182-
183-
// Compute the zero commitment if not found.
184-
c.unwrap_or_else(|| ED25519_BASEPOINT_POINT + *H * Scalar::from(amount))
185-
};
159+
let commitment = compute_zero_commitments(amount);
186160

187161
let time_lock = if output
188162
.output_flags

storage/blockchain/src/ops/tx.rs

Lines changed: 9 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@
22
33
//---------------------------------------------------------------------------------------------------- Import
44
use bytemuck::TransparentWrapper;
5-
use curve25519_dalek::{
6-
constants::ED25519_BASEPOINT_POINT, edwards::CompressedEdwardsY, EdwardsPoint, Scalar,
7-
};
85
use monero_serai::transaction::{Input, Timelock, Transaction};
96

10-
use cuprate_constants::crypto::ZERO_COMMITMENT_LOOKUP_TABLE as ZC_LT;
117
use cuprate_database::{DatabaseRo, DatabaseRw, RuntimeError, StorableVec};
8+
use cuprate_helper::crypto::compute_zero_commitments;
129

1310
use crate::{
1411
ops::{
@@ -140,48 +137,14 @@ pub fn add_tx(
140137
.map(|(i, output)| {
141138
// Create commitment.
142139

143-
// Binary search in lookup table (O(log2(n)+2) instead of O(n+2))
144-
let commitment: EdwardsPoint = {
145-
let (mut start, mut end, mut c, amount): (
146-
usize,
147-
usize,
148-
Option<EdwardsPoint>,
149-
u64,
150-
) = (0, (ZC_LT.len() - 1) / 2, None, output.amount.unwrap_or(0));
151-
while start <= end {
152-
let mid = (start + end) / 2;
153-
let lookup = ZC_LT[mid].0;
154-
match amount {
155-
a if a == lookup => {
156-
c = CompressedEdwardsY::from_slice(&ZC_LT[mid].1)
157-
.expect(
158-
"The lookup table cannot contain invalid curve point data",
159-
)
160-
.decompress();
161-
}
162-
a if a < lookup => {
163-
end = mid - 1;
164-
}
165-
_ => {
166-
start = mid + 1;
167-
}
168-
}
169-
}
170-
171-
// Compute commitment if not found.
172-
c.unwrap_or_else(|| {
173-
if miner_tx {
174-
ED25519_BASEPOINT_POINT
175-
+ *monero_serai::generators::H
176-
* Scalar::from(output.amount.unwrap_or(0))
177-
} else {
178-
proofs
179-
.as_ref()
180-
.expect("A V2 transaction with no RCT proofs is a miner tx")
181-
.base
182-
.commitments[i]
183-
}
184-
})
140+
let commitment = if miner_tx {
141+
compute_zero_commitments(output.amount.unwrap_or(0))
142+
} else {
143+
proofs
144+
.as_ref()
145+
.expect("A V2 transaction with no RCT proofs is a miner tx")
146+
.base
147+
.commitments[i]
185148
};
186149

187150
// Add the RCT output.

0 commit comments

Comments
 (0)