mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-18 16:55:16 +00:00
Generate Bulletproofs(+) generators at compile time
Creates a new monero-generators crate so the monero crate can run the code in question at build time. Saves several seconds from running the tests. Closes https://github.com/serai-dex/serai/issues/101.
This commit is contained in:
parent
577fe99a08
commit
603a3f8c9f
19 changed files with 274 additions and 133 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -4583,6 +4583,18 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monero-generators"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"curve25519-dalek 3.2.0",
|
||||
"dalek-ff-group",
|
||||
"group",
|
||||
"lazy_static",
|
||||
"subtle",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "monero-serai"
|
||||
version = "0.1.0"
|
||||
|
@ -4600,6 +4612,7 @@ dependencies = [
|
|||
"modular-frost",
|
||||
"monero",
|
||||
"monero-epee-bin-serde",
|
||||
"monero-generators",
|
||||
"multiexp",
|
||||
"rand 0.8.5",
|
||||
"rand_chacha 0.3.1",
|
||||
|
@ -4608,7 +4621,6 @@ dependencies = [
|
|||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.2",
|
||||
"subtle",
|
||||
"thiserror",
|
||||
"tiny-keccak",
|
||||
|
|
|
@ -9,6 +9,7 @@ members = [
|
|||
"crypto/frost",
|
||||
|
||||
"coins/ethereum",
|
||||
"coins/monero/generators",
|
||||
"coins/monero",
|
||||
|
||||
"processor",
|
||||
|
|
1
coins/monero/.gitignore
vendored
Normal file
1
coins/monero/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.generators
|
|
@ -32,6 +32,8 @@ transcript = { package = "flexible-transcript", path = "../../crypto/transcript"
|
|||
frost = { package = "modular-frost", path = "../../crypto/frost", features = ["ed25519"], optional = true }
|
||||
dleq = { path = "../../crypto/dleq", features = ["serialize"], optional = true }
|
||||
|
||||
monero-generators = { path = "generators" }
|
||||
|
||||
hex = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
@ -45,6 +47,9 @@ reqwest = { version = "0.11", features = ["json"] }
|
|||
[features]
|
||||
multisig = ["rand_chacha", "blake2", "transcript", "frost", "dleq"]
|
||||
|
||||
[build-dependencies]
|
||||
dalek-ff-group = { path = "../../crypto/dalek-ff-group" }
|
||||
monero-generators = { path = "generators" }
|
||||
|
||||
[dev-dependencies]
|
||||
sha2 = "0.10"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
|
|
67
coins/monero/build.rs
Normal file
67
coins/monero/build.rs
Normal file
|
@ -0,0 +1,67 @@
|
|||
use std::{
|
||||
io::Write,
|
||||
path::Path,
|
||||
fs::{File, remove_file},
|
||||
};
|
||||
|
||||
use dalek_ff_group::EdwardsPoint;
|
||||
|
||||
use monero_generators::bulletproofs_generators;
|
||||
|
||||
fn serialize(generators_string: &mut String, points: &[EdwardsPoint]) {
|
||||
for generator in points {
|
||||
generators_string.extend(
|
||||
format!(
|
||||
"
|
||||
dalek_ff_group::EdwardsPoint(
|
||||
curve25519_dalek::edwards::CompressedEdwardsY({:?}).decompress().unwrap()
|
||||
),
|
||||
",
|
||||
generator.compress().to_bytes()
|
||||
)
|
||||
.chars(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn generators(prefix: &'static str, path: &str) {
|
||||
let generators = bulletproofs_generators(prefix.as_bytes());
|
||||
#[allow(non_snake_case)]
|
||||
let mut G_str = "".to_string();
|
||||
serialize(&mut G_str, &generators.G);
|
||||
#[allow(non_snake_case)]
|
||||
let mut H_str = "".to_string();
|
||||
serialize(&mut H_str, &generators.H);
|
||||
|
||||
let path = Path::new(".generators").join(path);
|
||||
let _ = remove_file(&path);
|
||||
File::create(&path)
|
||||
.unwrap()
|
||||
.write_all(
|
||||
format!(
|
||||
"
|
||||
lazy_static! {{
|
||||
static ref GENERATORS: Generators = Generators {{
|
||||
G: [
|
||||
{}
|
||||
],
|
||||
H: [
|
||||
{}
|
||||
],
|
||||
}};
|
||||
}}
|
||||
",
|
||||
G_str, H_str,
|
||||
)
|
||||
.as_bytes(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// For some reason, filtering off .generators does not work. This prevents re-building overall
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
generators("bulletproof", "generators.rs");
|
||||
generators("bulletproof_plus", "generators_plus.rs");
|
||||
}
|
19
coins/monero/generators/Cargo.toml
Normal file
19
coins/monero/generators/Cargo.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "monero-generators"
|
||||
version = "0.1.0"
|
||||
description = "Monero's hash_to_point and generators"
|
||||
license = "MIT"
|
||||
authors = ["Luke Parker <lukeparker5132@gmail.com>"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1"
|
||||
|
||||
subtle = "2.4"
|
||||
|
||||
tiny-keccak = { version = "2", features = ["keccak"] }
|
||||
|
||||
curve25519-dalek = { version = "3", features = ["std"] }
|
||||
|
||||
group = { version = "0.12" }
|
||||
dalek-ff-group = { path = "../../../crypto/dalek-ff-group" }
|
21
coins/monero/generators/LICENSE
Normal file
21
coins/monero/generators/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2022 Luke Parker
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
51
coins/monero/generators/src/hash_to_point.rs
Normal file
51
coins/monero/generators/src/hash_to_point.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use subtle::ConditionallySelectable;
|
||||
|
||||
use curve25519_dalek::edwards::{EdwardsPoint, CompressedEdwardsY};
|
||||
|
||||
use group::ff::{Field, PrimeField};
|
||||
use dalek_ff_group::field::FieldElement;
|
||||
|
||||
use crate::hash;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn hash_to_point(bytes: [u8; 32]) -> EdwardsPoint {
|
||||
#[allow(non_snake_case)]
|
||||
let A = FieldElement::from(486662u64);
|
||||
|
||||
let v = FieldElement::from_square(hash(&bytes)).double();
|
||||
let w = v + FieldElement::one();
|
||||
let x = w.square() + (-A.square() * v);
|
||||
|
||||
// This isn't the complete X, yet its initial value
|
||||
// We don't calculate the full X, and instead solely calculate Y, letting dalek reconstruct X
|
||||
// While inefficient, it solves API boundaries and reduces the amount of work done here
|
||||
#[allow(non_snake_case)]
|
||||
let X = {
|
||||
let u = w;
|
||||
let v = x;
|
||||
let v3 = v * v * v;
|
||||
let uv3 = u * v3;
|
||||
let v7 = v3 * v3 * v;
|
||||
let uv7 = u * v7;
|
||||
uv3 * uv7.pow((-FieldElement::from(5u8)) * FieldElement::from(8u8).invert().unwrap())
|
||||
};
|
||||
let x = X.square() * x;
|
||||
|
||||
let y = w - x;
|
||||
let non_zero_0 = !y.is_zero();
|
||||
let y_if_non_zero_0 = w + x;
|
||||
let sign = non_zero_0 & (!y_if_non_zero_0.is_zero());
|
||||
|
||||
let mut z = -A;
|
||||
z *= FieldElement::conditional_select(&v, &FieldElement::from(1u8), sign);
|
||||
#[allow(non_snake_case)]
|
||||
let Z = z + w;
|
||||
#[allow(non_snake_case)]
|
||||
let mut Y = z - w;
|
||||
|
||||
Y *= Z.invert().unwrap();
|
||||
let mut bytes = Y.to_repr();
|
||||
bytes[31] |= sign.unwrap_u8() << 7;
|
||||
|
||||
CompressedEdwardsY(bytes).decompress().unwrap().mul_by_cofactor()
|
||||
}
|
61
coins/monero/generators/src/lib.rs
Normal file
61
coins/monero/generators/src/lib.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use lazy_static::lazy_static;
|
||||
|
||||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
||||
use curve25519_dalek::{
|
||||
constants::ED25519_BASEPOINT_POINT,
|
||||
edwards::{EdwardsPoint as DalekPoint, CompressedEdwardsY},
|
||||
};
|
||||
|
||||
use group::Group;
|
||||
use dalek_ff_group::EdwardsPoint;
|
||||
|
||||
mod varint;
|
||||
use varint::write_varint;
|
||||
|
||||
mod hash_to_point;
|
||||
pub use hash_to_point::hash_to_point;
|
||||
|
||||
fn hash(data: &[u8]) -> [u8; 32] {
|
||||
let mut keccak = Keccak::v256();
|
||||
keccak.update(data);
|
||||
let mut res = [0; 32];
|
||||
keccak.finalize(&mut res);
|
||||
res
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref H: DalekPoint =
|
||||
CompressedEdwardsY(hash(&ED25519_BASEPOINT_POINT.compress().to_bytes()))
|
||||
.decompress()
|
||||
.unwrap()
|
||||
.mul_by_cofactor();
|
||||
}
|
||||
|
||||
const MAX_M: usize = 16;
|
||||
const N: usize = 64;
|
||||
const MAX_MN: usize = MAX_M * N;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub struct Generators {
|
||||
pub G: [EdwardsPoint; MAX_MN],
|
||||
pub H: [EdwardsPoint; MAX_MN],
|
||||
}
|
||||
|
||||
pub fn bulletproofs_generators(prefix: &'static [u8]) -> Generators {
|
||||
let mut res =
|
||||
Generators { G: [EdwardsPoint::identity(); MAX_MN], H: [EdwardsPoint::identity(); MAX_MN] };
|
||||
for i in 0 .. MAX_MN {
|
||||
let i = 2 * i;
|
||||
|
||||
let mut even = H.compress().to_bytes().to_vec();
|
||||
even.extend(prefix);
|
||||
let mut odd = even.clone();
|
||||
|
||||
write_varint(&i.try_into().unwrap(), &mut even).unwrap();
|
||||
write_varint(&(i + 1).try_into().unwrap(), &mut odd).unwrap();
|
||||
res.H[i / 2] = EdwardsPoint(hash_to_point(hash(&even)));
|
||||
res.G[i / 2] = EdwardsPoint(hash_to_point(hash(&odd)));
|
||||
}
|
||||
res
|
||||
}
|
16
coins/monero/generators/src/varint.rs
Normal file
16
coins/monero/generators/src/varint.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use std::io;
|
||||
|
||||
const VARINT_CONTINUATION_MASK: u8 = 0b1000_0000;
|
||||
pub(crate) fn write_varint<W: io::Write>(varint: &u64, w: &mut W) -> io::Result<()> {
|
||||
let mut varint = *varint;
|
||||
while {
|
||||
let mut b = u8::try_from(varint & u64::from(!VARINT_CONTINUATION_MASK)).unwrap();
|
||||
varint >>= 7;
|
||||
if varint != 0 {
|
||||
b |= VARINT_CONTINUATION_MASK;
|
||||
}
|
||||
w.write_all(&[b])?;
|
||||
varint != 0
|
||||
} {}
|
||||
Ok(())
|
||||
}
|
|
@ -6,11 +6,13 @@ use zeroize::{Zeroize, ZeroizeOnDrop};
|
|||
use tiny_keccak::{Hasher, Keccak};
|
||||
|
||||
use curve25519_dalek::{
|
||||
constants::{ED25519_BASEPOINT_POINT, ED25519_BASEPOINT_TABLE},
|
||||
constants::ED25519_BASEPOINT_TABLE,
|
||||
scalar::Scalar,
|
||||
edwards::{EdwardsPoint, EdwardsBasepointTable, CompressedEdwardsY},
|
||||
edwards::{EdwardsPoint, EdwardsBasepointTable},
|
||||
};
|
||||
|
||||
pub use monero_generators::H;
|
||||
|
||||
#[cfg(feature = "multisig")]
|
||||
pub mod frost;
|
||||
|
||||
|
@ -54,11 +56,6 @@ impl Protocol {
|
|||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref H: EdwardsPoint =
|
||||
CompressedEdwardsY(hash(&ED25519_BASEPOINT_POINT.compress().to_bytes()))
|
||||
.decompress()
|
||||
.unwrap()
|
||||
.mul_by_cofactor();
|
||||
static ref H_TABLE: EdwardsBasepointTable = EdwardsBasepointTable::create(&H);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,10 +13,9 @@ use dalek_ff_group::{Scalar, EdwardsPoint};
|
|||
|
||||
use multiexp::multiexp as multiexp_const;
|
||||
|
||||
use crate::{
|
||||
H as DALEK_H, Commitment, hash, hash_to_scalar as dalek_hash,
|
||||
ringct::hash_to_point::raw_hash_to_point, serialize::write_varint,
|
||||
};
|
||||
pub(crate) use monero_generators::Generators;
|
||||
|
||||
use crate::{H as DALEK_H, Commitment, hash_to_scalar as dalek_hash};
|
||||
pub(crate) use crate::ringct::bulletproofs::scalar_vector::*;
|
||||
|
||||
// Bring things into ff/group
|
||||
|
@ -33,29 +32,6 @@ pub(crate) fn hash_to_scalar(data: &[u8]) -> Scalar {
|
|||
pub(crate) const MAX_M: usize = 16;
|
||||
pub(crate) const LOG_N: usize = 6; // 2 << 6 == N
|
||||
pub(crate) const N: usize = 64;
|
||||
pub(crate) const MAX_MN: usize = MAX_M * N;
|
||||
|
||||
pub(crate) struct Generators {
|
||||
pub(crate) G: Vec<EdwardsPoint>,
|
||||
pub(crate) H: Vec<EdwardsPoint>,
|
||||
}
|
||||
|
||||
pub(crate) fn generators_core(prefix: &'static [u8]) -> Generators {
|
||||
let mut res = Generators { G: Vec::with_capacity(MAX_MN), H: Vec::with_capacity(MAX_MN) };
|
||||
for i in 0 .. MAX_MN {
|
||||
let i = 2 * i;
|
||||
|
||||
let mut even = (*H).compress().to_bytes().to_vec();
|
||||
even.extend(prefix);
|
||||
let mut odd = even.clone();
|
||||
|
||||
write_varint(&i.try_into().unwrap(), &mut even).unwrap();
|
||||
write_varint(&(i + 1).try_into().unwrap(), &mut odd).unwrap();
|
||||
res.H.push(EdwardsPoint(raw_hash_to_point(hash(&even))));
|
||||
res.G.push(EdwardsPoint(raw_hash_to_point(hash(&odd))));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
pub(crate) fn prove_multiexp(pairs: &[(Scalar, EdwardsPoint)]) -> EdwardsPoint {
|
||||
multiexp_const(pairs) * *INV_EIGHT
|
||||
|
@ -153,12 +129,6 @@ lazy_static! {
|
|||
pub(crate) static ref TWO_N: ScalarVector = ScalarVector::powers(Scalar::from(2u8), N);
|
||||
}
|
||||
|
||||
pub(crate) fn init() {
|
||||
let _ = &*INV_EIGHT;
|
||||
let _ = &*H;
|
||||
let _ = &*TWO_N;
|
||||
}
|
||||
|
||||
pub(crate) fn challenge_products(w: &[Scalar], winv: &[Scalar]) -> Vec<Scalar> {
|
||||
let mut products = vec![Scalar::zero(); 1 << w.len()];
|
||||
products[0] = winv[0];
|
||||
|
|
|
@ -43,14 +43,6 @@ impl Bulletproofs {
|
|||
len + clawback
|
||||
}
|
||||
|
||||
pub fn init(plus: bool) {
|
||||
if !plus {
|
||||
OriginalStruct::init();
|
||||
} else {
|
||||
PlusStruct::init();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn prove<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
outputs: &[Commitment],
|
||||
|
|
|
@ -12,8 +12,9 @@ use multiexp::BatchVerifier;
|
|||
|
||||
use crate::{Commitment, ringct::bulletproofs::core::*};
|
||||
|
||||
include!("../../../.generators/generators.rs");
|
||||
|
||||
lazy_static! {
|
||||
static ref GENERATORS: Generators = generators_core(b"bulletproof");
|
||||
static ref ONE_N: ScalarVector = ScalarVector(vec![Scalar::one(); N]);
|
||||
static ref IP12: Scalar = inner_product(&ONE_N, &TWO_N);
|
||||
}
|
||||
|
@ -34,13 +35,6 @@ pub struct OriginalStruct {
|
|||
}
|
||||
|
||||
impl OriginalStruct {
|
||||
pub(crate) fn init() {
|
||||
init();
|
||||
let _ = &*GENERATORS;
|
||||
let _ = &*ONE_N;
|
||||
let _ = &*IP12;
|
||||
}
|
||||
|
||||
pub(crate) fn prove<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
commitments: &[Commitment],
|
||||
|
|
|
@ -15,8 +15,9 @@ use crate::{
|
|||
ringct::{hash_to_point::raw_hash_to_point, bulletproofs::core::*},
|
||||
};
|
||||
|
||||
include!("../../../.generators/generators_plus.rs");
|
||||
|
||||
lazy_static! {
|
||||
static ref GENERATORS: Generators = generators_core(b"bulletproof_plus");
|
||||
static ref TRANSCRIPT: [u8; 32] =
|
||||
EdwardsPoint(raw_hash_to_point(hash(b"bulletproof_plus_transcript"))).compress().to_bytes();
|
||||
}
|
||||
|
@ -52,12 +53,6 @@ pub struct PlusStruct {
|
|||
}
|
||||
|
||||
impl PlusStruct {
|
||||
pub(crate) fn init() {
|
||||
init();
|
||||
let _ = &*GENERATORS;
|
||||
let _ = &*TRANSCRIPT;
|
||||
}
|
||||
|
||||
pub(crate) fn prove<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
commitments: &[Commitment],
|
||||
|
|
|
@ -1,54 +1,6 @@
|
|||
use subtle::ConditionallySelectable;
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
|
||||
use curve25519_dalek::edwards::{CompressedEdwardsY, EdwardsPoint};
|
||||
|
||||
use group::ff::{Field, PrimeField};
|
||||
use dalek_ff_group::field::FieldElement;
|
||||
|
||||
use crate::hash;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn raw_hash_to_point(bytes: [u8; 32]) -> EdwardsPoint {
|
||||
#[allow(non_snake_case)]
|
||||
let A = FieldElement::from(486662u64);
|
||||
|
||||
let v = FieldElement::from_square(hash(&bytes)).double();
|
||||
let w = v + FieldElement::one();
|
||||
let x = w.square() + (-A.square() * v);
|
||||
|
||||
// This isn't the complete X, yet its initial value
|
||||
// We don't calculate the full X, and instead solely calculate Y, letting dalek reconstruct X
|
||||
// While inefficient, it solves API boundaries and reduces the amount of work done here
|
||||
#[allow(non_snake_case)]
|
||||
let X = {
|
||||
let u = w;
|
||||
let v = x;
|
||||
let v3 = v * v * v;
|
||||
let uv3 = u * v3;
|
||||
let v7 = v3 * v3 * v;
|
||||
let uv7 = u * v7;
|
||||
uv3 * uv7.pow((-FieldElement::from(5u8)) * FieldElement::from(8u8).invert().unwrap())
|
||||
};
|
||||
let x = X.square() * x;
|
||||
|
||||
let y = w - x;
|
||||
let non_zero_0 = !y.is_zero();
|
||||
let y_if_non_zero_0 = w + x;
|
||||
let sign = non_zero_0 & (!y_if_non_zero_0.is_zero());
|
||||
|
||||
let mut z = -A;
|
||||
z *= FieldElement::conditional_select(&v, &FieldElement::from(1u8), sign);
|
||||
#[allow(non_snake_case)]
|
||||
let Z = z + w;
|
||||
#[allow(non_snake_case)]
|
||||
let mut Y = z - w;
|
||||
|
||||
Y *= Z.invert().unwrap();
|
||||
let mut bytes = Y.to_repr();
|
||||
bytes[31] |= sign.unwrap_u8() << 7;
|
||||
|
||||
CompressedEdwardsY(bytes).decompress().unwrap().mul_by_cofactor()
|
||||
}
|
||||
pub(crate) use monero_generators::{hash_to_point as raw_hash_to_point};
|
||||
|
||||
pub fn hash_to_point(key: EdwardsPoint) -> EdwardsPoint {
|
||||
raw_hash_to_point(key.compress().to_bytes())
|
||||
|
|
|
@ -57,12 +57,7 @@ fn bulletproofs_vector() {
|
|||
}
|
||||
|
||||
macro_rules! bulletproofs_tests {
|
||||
($init: ident, $name: ident, $max: ident, $plus: literal) => {
|
||||
#[test]
|
||||
fn $init() {
|
||||
Bulletproofs::init($plus);
|
||||
}
|
||||
|
||||
($name: ident, $max: ident, $plus: literal) => {
|
||||
#[test]
|
||||
fn $name() {
|
||||
// Create Bulletproofs for all possible output quantities
|
||||
|
@ -93,5 +88,5 @@ macro_rules! bulletproofs_tests {
|
|||
};
|
||||
}
|
||||
|
||||
bulletproofs_tests!(bulletproofs_init, bulletproofs, bulletproofs_max, false);
|
||||
bulletproofs_tests!(bulletproofs_plus_init, bulletproofs_plus, bulletproofs_plus_max, true);
|
||||
bulletproofs_tests!(bulletproofs, bulletproofs_max, false);
|
||||
bulletproofs_tests!(bulletproofs_plus, bulletproofs_plus_max, true);
|
||||
|
|
|
@ -7,7 +7,6 @@ use transcript::RecommendedTranscript;
|
|||
use frost::{curve::Ed25519, FrostKeys};
|
||||
|
||||
use monero_serai::{
|
||||
ringct::bulletproofs::Bulletproofs,
|
||||
transaction::Transaction,
|
||||
rpc::Rpc,
|
||||
wallet::{
|
||||
|
@ -69,14 +68,7 @@ pub struct Monero {
|
|||
|
||||
impl Monero {
|
||||
pub async fn new(url: String) -> Monero {
|
||||
let view = view_key::<Monero>(0).0;
|
||||
let res = Monero { rpc: Rpc::new(url), view };
|
||||
|
||||
// Initialize Bulletproofs now to prevent the first call from taking several seconds
|
||||
// TODO: Do this for both, unless we're sure we're only working on a single protocol
|
||||
Bulletproofs::init(res.rpc.get_protocol().await.unwrap().bp_plus());
|
||||
|
||||
res
|
||||
Monero { rpc: Rpc::new(url), view: view_key::<Monero>(0).0 }
|
||||
}
|
||||
|
||||
fn view_pair(&self, spend: dfg::EdwardsPoint) -> ViewPair {
|
||||
|
|
|
@ -86,7 +86,7 @@ impl CoinDb for MemCoinDb {
|
|||
fn add_output<O: Output>(&mut self, output: &O) -> bool {
|
||||
// This would be insecure as we're indexing by ID and this will replace the output as a whole
|
||||
// Multiple outputs may have the same ID in edge cases such as Monero, where outputs are ID'd
|
||||
// by key image, not by hash + index
|
||||
// by output key, not by hash + index
|
||||
// self.outputs.insert(output.id(), output).is_some()
|
||||
let id = output.id().as_ref().to_vec();
|
||||
if self.outputs.contains_key(&id) {
|
||||
|
|
Loading…
Reference in a new issue