mirror of
https://github.com/serai-dex/serai.git
synced 2024-11-16 17:07:35 +00:00
Refine from pedantic, remove erratic consts
This commit is contained in:
parent
286e96ccd8
commit
3ca76c51e4
36 changed files with 192 additions and 335 deletions
|
@ -1,42 +1,26 @@
|
|||
# No warnings allowed
|
||||
-D warnings
|
||||
|
||||
# Non-default groups
|
||||
# nursery
|
||||
-D clippy::nursery
|
||||
-D clippy::pedantic
|
||||
|
||||
# Not worth the effort
|
||||
-A clippy::implicit_hasher
|
||||
|
||||
# Stylistic preferrence
|
||||
-A clippy::option_if_let_else
|
||||
|
||||
# Erratic and unhelpful
|
||||
-A clippy::missing_const_for_fn
|
||||
# Too many false/irrelevant positives
|
||||
-A clippy::redundant_pub_crate
|
||||
-A clippy::similar_names
|
||||
|
||||
# Flags on any debug_assert using an RNG
|
||||
-A clippy::debug_assert_with_mut_call
|
||||
# Stylistic preference
|
||||
-A clippy::option_if_let_else
|
||||
|
||||
# Frequently used
|
||||
-A clippy::large_types_passed_by_value
|
||||
-A clippy::wildcard_imports
|
||||
-A clippy::too_many_lines
|
||||
# pedantic
|
||||
-D clippy::unnecessary_wraps
|
||||
-D clippy::unused_async
|
||||
-D clippy::unused_self
|
||||
|
||||
# Used to avoid doing &* on copy-able items, with the * being the concern
|
||||
-A clippy::explicit_deref_methods
|
||||
|
||||
# Lints from clippy::restrictions
|
||||
|
||||
# These are relevant for crates we want to be no-std, eventually, and aren't
|
||||
# relevant for the rest
|
||||
-D clippy::std_instead_of_alloc
|
||||
-D clippy::std_instead_of_core
|
||||
-D clippy::alloc_instead_of_core
|
||||
# restrictions
|
||||
|
||||
# Safety
|
||||
-D clippy::as_conversions
|
||||
-D clippy::float_cmp_const
|
||||
-D clippy::disallowed_script_idents
|
||||
-D clippy::wildcard_enum_match_arm
|
||||
|
||||
|
@ -54,19 +38,10 @@
|
|||
-D clippy::format_push_string
|
||||
-D clippy::string_to_string
|
||||
|
||||
# Flagged on tests being named test_
|
||||
-A clippy::module_name_repetitions
|
||||
|
||||
# Flagged on items passed by value which implemented Copy
|
||||
-A clippy::needless_pass_by_value
|
||||
|
||||
# Flagged on embedded functions defined when needed/relevant
|
||||
-A clippy::items_after_statements
|
||||
|
||||
# These potentially should be enabled in the future
|
||||
-A clippy::missing_errors_doc
|
||||
-A clippy::missing_panics_doc
|
||||
-A clippy::doc_markdown
|
||||
# -D clippy::missing_errors_doc
|
||||
# -D clippy::missing_panics_doc
|
||||
# -D clippy::doc_markdown
|
||||
|
||||
# TODO: Enable this
|
||||
# -D clippy::cargo
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::hash;
|
|||
|
||||
/// Monero's hash to point function, as named `ge_fromfe_frombytes_vartime`.
|
||||
#[allow(clippy::many_single_char_names)]
|
||||
#[must_use]
|
||||
pub fn hash_to_point(bytes: [u8; 32]) -> EdwardsPoint {
|
||||
#[allow(non_snake_case, clippy::unreadable_literal)]
|
||||
let A = FieldElement::from(486662u64);
|
||||
|
|
|
@ -61,7 +61,6 @@ pub struct Generators {
|
|||
}
|
||||
|
||||
/// Generate generators as needed for Bulletproofs(+), as Monero does.
|
||||
#[must_use]
|
||||
pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators {
|
||||
let mut res =
|
||||
Generators { G: [EdwardsPoint::identity(); MAX_MN], H: [EdwardsPoint::identity(); MAX_MN] };
|
||||
|
|
|
@ -33,7 +33,6 @@ impl BlockHeader {
|
|||
w.write_all(&self.nonce.to_le_bytes())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = vec![];
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
@ -59,7 +58,6 @@ pub struct Block {
|
|||
}
|
||||
|
||||
impl Block {
|
||||
#[must_use]
|
||||
pub fn number(&self) -> usize {
|
||||
match self.miner_tx.prefix.inputs.get(0) {
|
||||
Some(Input::Gen(number)) => (*number).try_into().unwrap(),
|
||||
|
@ -93,7 +91,6 @@ impl Block {
|
|||
out
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn hash(&self) -> [u8; 32] {
|
||||
let hash = hash(&self.serialize_hashable());
|
||||
if hash == CORRECT_BLOCK_HASH_202612 {
|
||||
|
@ -103,7 +100,6 @@ impl Block {
|
|||
hash
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = vec![];
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
|
|
@ -60,7 +60,6 @@ pub enum Protocol {
|
|||
|
||||
impl Protocol {
|
||||
/// Amount of ring members under this protocol version.
|
||||
#[must_use]
|
||||
pub const fn ring_len(&self) -> usize {
|
||||
match self {
|
||||
Self::v14 => 11,
|
||||
|
@ -72,7 +71,6 @@ impl Protocol {
|
|||
/// Whether or not the specified version uses Bulletproofs or Bulletproofs+.
|
||||
///
|
||||
/// This method will likely be reworked when versions not using Bulletproofs at all are added.
|
||||
#[must_use]
|
||||
pub const fn bp_plus(&self) -> bool {
|
||||
match self {
|
||||
Self::v14 => false,
|
||||
|
@ -82,7 +80,6 @@ impl Protocol {
|
|||
}
|
||||
|
||||
// TODO: Make this an Option when we support pre-RCT protocols
|
||||
#[must_use]
|
||||
pub const fn optimal_rct_type(&self) -> RctType {
|
||||
match self {
|
||||
Self::v14 => RctType::Clsag,
|
||||
|
@ -144,25 +141,21 @@ pub struct Commitment {
|
|||
|
||||
impl Commitment {
|
||||
/// A commitment to zero, defined with a mask of 1 (as to not be the identity).
|
||||
#[must_use]
|
||||
pub fn zero() -> Self {
|
||||
Self { mask: Scalar::one(), amount: 0 }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn new(mask: Scalar, amount: u64) -> Self {
|
||||
pub fn new(mask: Scalar, amount: u64) -> Self {
|
||||
Self { mask, amount }
|
||||
}
|
||||
|
||||
/// Calculate a Pedersen commitment, as a point, from the transparent structure.
|
||||
#[must_use]
|
||||
pub fn calculate(&self) -> EdwardsPoint {
|
||||
(&self.mask * &ED25519_BASEPOINT_TABLE) + (Scalar::from(self.amount) * H())
|
||||
}
|
||||
}
|
||||
|
||||
/// Support generating a random scalar using a modern rand, as dalek's is notoriously dated.
|
||||
#[must_use]
|
||||
pub fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Scalar {
|
||||
let mut r = [0; 64];
|
||||
rng.fill_bytes(&mut r);
|
||||
|
@ -174,7 +167,6 @@ pub(crate) fn hash(data: &[u8]) -> [u8; 32] {
|
|||
}
|
||||
|
||||
/// Hash the provided data to a scalar via keccak256(data) % l.
|
||||
#[must_use]
|
||||
pub fn hash_to_scalar(data: &[u8]) -> Scalar {
|
||||
let scalar = Scalar::from_bytes_mod_order(hash(data));
|
||||
// Monero will explicitly error in this case
|
||||
|
|
|
@ -2,7 +2,6 @@ use std_shims::vec::Vec;
|
|||
|
||||
use crate::hash;
|
||||
|
||||
#[must_use]
|
||||
pub(crate) fn merkle_root(root: [u8; 32], leafs: &[[u8; 32]]) -> [u8; 32] {
|
||||
match leafs.len() {
|
||||
0 => root,
|
||||
|
|
|
@ -56,7 +56,7 @@ pub(crate) fn hash_cache(cache: &mut Scalar, mash: &[[u8; 32]]) -> Scalar {
|
|||
*cache
|
||||
}
|
||||
|
||||
pub(crate) const fn MN(outputs: usize) -> (usize, usize, usize) {
|
||||
pub(crate) fn MN(outputs: usize) -> (usize, usize, usize) {
|
||||
let mut logM = 0;
|
||||
let mut M;
|
||||
while {
|
||||
|
|
|
@ -140,7 +140,6 @@ impl Bulletproofs {
|
|||
self.write_core(w, |points, w| write_vec(write_point, points, w))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = vec![];
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
|
|
@ -6,10 +6,9 @@ use std_shims::{
|
|||
io::{self, Read, Write},
|
||||
};
|
||||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
use subtle::{ConstantTimeEq, Choice, CtOption};
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use curve25519_dalek::{
|
||||
constants::ED25519_BASEPOINT_TABLE,
|
||||
|
@ -30,31 +29,27 @@ pub use multisig::{ClsagDetails, ClsagAddendum, ClsagMultisig};
|
|||
#[cfg(feature = "multisig")]
|
||||
pub(crate) use multisig::add_key_image_share;
|
||||
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod clsag_error {
|
||||
/// Errors returned when CLSAG signing fails.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
pub enum ClsagError {
|
||||
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
||||
InternalError(&'static str),
|
||||
#[cfg_attr(feature = "std", error("invalid ring"))]
|
||||
InvalidRing,
|
||||
#[cfg_attr(feature = "std", error("invalid ring member (member {0}, ring size {1})"))]
|
||||
InvalidRingMember(u8, u8),
|
||||
#[cfg_attr(feature = "std", error("invalid commitment"))]
|
||||
InvalidCommitment,
|
||||
#[cfg_attr(feature = "std", error("invalid key image"))]
|
||||
InvalidImage,
|
||||
#[cfg_attr(feature = "std", error("invalid D"))]
|
||||
InvalidD,
|
||||
#[cfg_attr(feature = "std", error("invalid s"))]
|
||||
InvalidS,
|
||||
#[cfg_attr(feature = "std", error("invalid c1"))]
|
||||
InvalidC1,
|
||||
}
|
||||
/// Errors returned when CLSAG signing fails.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
pub enum ClsagError {
|
||||
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
||||
InternalError(&'static str),
|
||||
#[cfg_attr(feature = "std", error("invalid ring"))]
|
||||
InvalidRing,
|
||||
#[cfg_attr(feature = "std", error("invalid ring member (member {0}, ring size {1})"))]
|
||||
InvalidRingMember(u8, u8),
|
||||
#[cfg_attr(feature = "std", error("invalid commitment"))]
|
||||
InvalidCommitment,
|
||||
#[cfg_attr(feature = "std", error("invalid key image"))]
|
||||
InvalidImage,
|
||||
#[cfg_attr(feature = "std", error("invalid D"))]
|
||||
InvalidD,
|
||||
#[cfg_attr(feature = "std", error("invalid s"))]
|
||||
InvalidS,
|
||||
#[cfg_attr(feature = "std", error("invalid c1"))]
|
||||
InvalidC1,
|
||||
}
|
||||
pub use clsag_error::ClsagError;
|
||||
|
||||
/// Input being signed for.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
|
||||
|
@ -239,7 +234,6 @@ impl Clsag {
|
|||
/// Generate CLSAG signatures for the given inputs.
|
||||
/// inputs is of the form (private key, key image, input).
|
||||
/// sum_outputs is for the sum of the outputs' commitment masks.
|
||||
#[must_use]
|
||||
pub fn sign<R: RngCore + CryptoRng>(
|
||||
rng: &mut R,
|
||||
mut inputs: Vec<(Zeroizing<Scalar>, EdwardsPoint, ClsagInput)>,
|
||||
|
@ -249,11 +243,12 @@ impl Clsag {
|
|||
let mut res = Vec::with_capacity(inputs.len());
|
||||
let mut sum_pseudo_outs = Scalar::zero();
|
||||
for i in 0 .. inputs.len() {
|
||||
let mut mask = random_scalar(rng);
|
||||
if i == (inputs.len() - 1) {
|
||||
mask = sum_outputs - sum_pseudo_outs;
|
||||
let mask = if i == (inputs.len() - 1) {
|
||||
sum_outputs - sum_pseudo_outs
|
||||
} else {
|
||||
let mask = random_scalar(rng);
|
||||
sum_pseudo_outs += mask;
|
||||
mask
|
||||
}
|
||||
|
||||
let mut nonce = Zeroizing::new(random_scalar(rng));
|
||||
|
@ -314,7 +309,7 @@ impl Clsag {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) const fn fee_weight(ring_len: usize) -> usize {
|
||||
pub(crate) fn fee_weight(ring_len: usize) -> usize {
|
||||
(ring_len * 32) + 32 + 32
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,6 @@ pub struct ClsagDetails {
|
|||
}
|
||||
|
||||
impl ClsagDetails {
|
||||
#[must_use]
|
||||
pub fn new(input: ClsagInput, mask: Scalar) -> Self {
|
||||
Self { input, mask }
|
||||
}
|
||||
|
@ -116,7 +115,6 @@ pub struct ClsagMultisig {
|
|||
}
|
||||
|
||||
impl ClsagMultisig {
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
transcript: RecommendedTranscript,
|
||||
output_key: EdwardsPoint,
|
||||
|
|
|
@ -3,7 +3,6 @@ use curve25519_dalek::edwards::EdwardsPoint;
|
|||
pub use monero_generators::{hash_to_point as raw_hash_to_point};
|
||||
|
||||
/// Monero's hash to point function, as named `ge_fromfe_frombytes_vartime`.
|
||||
#[must_use]
|
||||
pub fn hash_to_point(key: EdwardsPoint) -> EdwardsPoint {
|
||||
raw_hash_to_point(key.compress().to_bytes())
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ use crate::{
|
|||
};
|
||||
|
||||
/// Generate a key image for a given key. Defined as `x * hash_to_point(xG)`.
|
||||
#[must_use]
|
||||
pub fn generate_key_image(secret: &Zeroizing<Scalar>) -> EdwardsPoint {
|
||||
hash_to_point(&ED25519_BASEPOINT_TABLE * secret.deref()) * secret.deref()
|
||||
}
|
||||
|
@ -78,8 +77,7 @@ pub enum RctType {
|
|||
}
|
||||
|
||||
impl RctType {
|
||||
#[must_use]
|
||||
pub const fn to_byte(self) -> u8 {
|
||||
pub fn to_byte(self) -> u8 {
|
||||
match self {
|
||||
Self::Null => 0,
|
||||
Self::MlsagAggregate => 1,
|
||||
|
@ -91,7 +89,6 @@ impl RctType {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn from_byte(byte: u8) -> Option<Self> {
|
||||
Some(match byte {
|
||||
0 => Self::Null,
|
||||
|
@ -105,8 +102,7 @@ impl RctType {
|
|||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn compact_encrypted_amounts(&self) -> bool {
|
||||
pub fn compact_encrypted_amounts(&self) -> bool {
|
||||
match self {
|
||||
Self::Null | Self::MlsagAggregate | Self::MlsagIndividual | Self::Bulletproofs => false,
|
||||
Self::BulletproofsCompactAmount | Self::Clsag | Self::BulletproofsPlus => true,
|
||||
|
@ -123,7 +119,7 @@ pub struct RctBase {
|
|||
}
|
||||
|
||||
impl RctBase {
|
||||
pub(crate) const fn fee_weight(outputs: usize) -> usize {
|
||||
pub(crate) fn fee_weight(outputs: usize) -> usize {
|
||||
1 + 8 + (outputs * (8 + 32))
|
||||
}
|
||||
|
||||
|
@ -245,7 +241,6 @@ impl RctPrunable {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self, rct_type: RctType) -> Vec<u8> {
|
||||
let mut serialized = vec![];
|
||||
self.write(&mut serialized, rct_type).unwrap();
|
||||
|
@ -312,7 +307,6 @@ pub struct RctSignatures {
|
|||
|
||||
impl RctSignatures {
|
||||
/// RctType for a given RctSignatures struct.
|
||||
#[must_use]
|
||||
pub fn rct_type(&self) -> RctType {
|
||||
match &self.prunable {
|
||||
RctPrunable::Null => RctType::Null,
|
||||
|
@ -376,7 +370,6 @@ impl RctSignatures {
|
|||
self.prunable.write(w, rct_type)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = vec![];
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
|
|
@ -47,31 +47,26 @@ struct TransactionsResponse {
|
|||
txs: Vec<TransactionResponse>,
|
||||
}
|
||||
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod rpc_error {
|
||||
use std_shims::{vec::Vec, string::String};
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
pub enum RpcError {
|
||||
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
||||
InternalError(&'static str),
|
||||
#[cfg_attr(feature = "std", error("connection error"))]
|
||||
ConnectionError,
|
||||
#[cfg_attr(feature = "std", error("invalid node"))]
|
||||
InvalidNode,
|
||||
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
|
||||
UnsupportedProtocol(usize),
|
||||
#[cfg_attr(feature = "std", error("transactions not found"))]
|
||||
TransactionsNotFound(Vec<[u8; 32]>),
|
||||
#[cfg_attr(feature = "std", error("invalid point ({0})"))]
|
||||
InvalidPoint(String),
|
||||
#[cfg_attr(feature = "std", error("pruned transaction"))]
|
||||
PrunedTransaction,
|
||||
#[cfg_attr(feature = "std", error("invalid transaction ({0:?})"))]
|
||||
InvalidTransaction([u8; 32]),
|
||||
}
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
pub enum RpcError {
|
||||
#[cfg_attr(feature = "std", error("internal error ({0})"))]
|
||||
InternalError(&'static str),
|
||||
#[cfg_attr(feature = "std", error("connection error"))]
|
||||
ConnectionError,
|
||||
#[cfg_attr(feature = "std", error("invalid node"))]
|
||||
InvalidNode,
|
||||
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
|
||||
UnsupportedProtocol(usize),
|
||||
#[cfg_attr(feature = "std", error("transactions not found"))]
|
||||
TransactionsNotFound(Vec<[u8; 32]>),
|
||||
#[cfg_attr(feature = "std", error("invalid point ({0})"))]
|
||||
InvalidPoint(String),
|
||||
#[cfg_attr(feature = "std", error("pruned transaction"))]
|
||||
PrunedTransaction,
|
||||
#[cfg_attr(feature = "std", error("invalid transaction ({0:?})"))]
|
||||
InvalidTransaction([u8; 32]),
|
||||
}
|
||||
pub use rpc_error::RpcError;
|
||||
|
||||
fn rpc_hex(value: &str) -> Result<Vec<u8>, RpcError> {
|
||||
hex::decode(value).map_err(|_| RpcError::InvalidNode)
|
||||
|
|
|
@ -25,7 +25,7 @@ pub enum Input {
|
|||
|
||||
impl Input {
|
||||
// Worst-case predictive len
|
||||
pub(crate) const fn fee_weight(ring_len: usize) -> usize {
|
||||
pub(crate) fn fee_weight(ring_len: usize) -> usize {
|
||||
// Uses 1 byte for the VarInt amount due to amount being 0
|
||||
// Uses 1 byte for the VarInt encoding of the length of the ring as well
|
||||
1 + 1 + 1 + (8 * ring_len) + 32
|
||||
|
@ -47,7 +47,6 @@ impl Input {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut res = vec![];
|
||||
self.write(&mut res).unwrap();
|
||||
|
@ -82,7 +81,7 @@ pub struct Output {
|
|||
}
|
||||
|
||||
impl Output {
|
||||
pub(crate) const fn fee_weight() -> usize {
|
||||
pub(crate) fn fee_weight() -> usize {
|
||||
1 + 1 + 32 + 1
|
||||
}
|
||||
|
||||
|
@ -96,7 +95,6 @@ impl Output {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut res = Vec::with_capacity(8 + 1 + 32);
|
||||
self.write(&mut res).unwrap();
|
||||
|
@ -202,7 +200,6 @@ impl TransactionPrefix {
|
|||
w.write_all(&self.extra)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut res = vec![];
|
||||
self.write(&mut res).unwrap();
|
||||
|
@ -235,7 +232,6 @@ impl TransactionPrefix {
|
|||
Ok(prefix)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn hash(&self) -> [u8; 32] {
|
||||
hash(&self.serialize())
|
||||
}
|
||||
|
@ -277,7 +273,6 @@ impl Transaction {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut res = Vec::with_capacity(2048);
|
||||
self.write(&mut res).unwrap();
|
||||
|
@ -336,7 +331,6 @@ impl Transaction {
|
|||
Ok(Self { prefix, signatures, rct_signatures })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn hash(&self) -> [u8; 32] {
|
||||
let mut buf = Vec::with_capacity(2048);
|
||||
if self.prefix.version == 1 {
|
||||
|
@ -365,7 +359,6 @@ impl Transaction {
|
|||
}
|
||||
|
||||
/// Calculate the hash of this transaction as needed for signing it.
|
||||
#[must_use]
|
||||
pub fn signature_hash(&self) -> [u8; 32] {
|
||||
let mut buf = Vec::with_capacity(2048);
|
||||
let mut sig_hash = Vec::with_capacity(96);
|
||||
|
|
|
@ -32,7 +32,6 @@ pub struct SubaddressIndex {
|
|||
}
|
||||
|
||||
impl SubaddressIndex {
|
||||
#[must_use]
|
||||
pub const fn new(account: u32, address: u32) -> Option<Self> {
|
||||
if (account == 0) && (address == 0) {
|
||||
return None;
|
||||
|
@ -40,12 +39,10 @@ impl SubaddressIndex {
|
|||
Some(Self { account, address })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn account(&self) -> u32 {
|
||||
self.account
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn address(&self) -> u32 {
|
||||
self.address
|
||||
}
|
||||
|
@ -61,12 +58,10 @@ pub enum AddressSpec {
|
|||
}
|
||||
|
||||
impl AddressType {
|
||||
#[must_use]
|
||||
pub const fn is_subaddress(&self) -> bool {
|
||||
matches!(self, Self::Subaddress) || matches!(self, Self::Featured { subaddress: true, .. })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn payment_id(&self) -> Option<[u8; 8]> {
|
||||
if let Self::Integrated(id) = self {
|
||||
Some(*id)
|
||||
|
@ -77,7 +72,6 @@ impl AddressType {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_guaranteed(&self) -> bool {
|
||||
matches!(self, Self::Featured { guaranteed: true, .. })
|
||||
}
|
||||
|
@ -147,7 +141,6 @@ impl<B: AddressBytes> AddressMeta<B> {
|
|||
}
|
||||
|
||||
/// Create an address's metadata.
|
||||
#[must_use]
|
||||
pub const fn new(network: Network, kind: AddressType) -> Self {
|
||||
Self { _bytes: PhantomData, network, kind }
|
||||
}
|
||||
|
@ -174,17 +167,14 @@ impl<B: AddressBytes> AddressMeta<B> {
|
|||
meta.ok_or(AddressError::InvalidByte)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_subaddress(&self) -> bool {
|
||||
self.kind.is_subaddress()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn payment_id(&self) -> Option<[u8; 8]> {
|
||||
self.kind.payment_id()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_guaranteed(&self) -> bool {
|
||||
self.kind.is_guaranteed()
|
||||
}
|
||||
|
@ -225,7 +215,6 @@ impl<B: AddressBytes> ToString for Address<B> {
|
|||
}
|
||||
|
||||
impl<B: AddressBytes> Address<B> {
|
||||
#[must_use]
|
||||
pub const fn new(meta: AddressMeta<B>, spend: EdwardsPoint, view: EdwardsPoint) -> Self {
|
||||
Self { meta, spend, view }
|
||||
}
|
||||
|
@ -290,22 +279,18 @@ impl<B: AddressBytes> Address<B> {
|
|||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn network(&self) -> Network {
|
||||
self.meta.network
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_subaddress(&self) -> bool {
|
||||
self.meta.is_subaddress()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn payment_id(&self) -> Option<[u8; 8]> {
|
||||
self.meta.payment_id()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn is_guaranteed(&self) -> bool {
|
||||
self.meta.is_guaranteed()
|
||||
}
|
||||
|
@ -316,7 +301,6 @@ pub type MoneroAddress = Address<MoneroAddressBytes>;
|
|||
// Allow re-interpreting of an arbitrary address as a Monero address so it can be used with the
|
||||
// rest of this library. Doesn't use From as it was conflicting with From<T> for T.
|
||||
impl MoneroAddress {
|
||||
#[must_use]
|
||||
pub const fn from<B: AddressBytes>(address: Address<B>) -> Self {
|
||||
Self::new(
|
||||
AddressMeta::new(address.meta.network, address.meta.kind),
|
||||
|
|
|
@ -24,6 +24,7 @@ const MATURITY: u64 = 60;
|
|||
const RECENT_WINDOW: usize = 15;
|
||||
const BLOCK_TIME: usize = 120;
|
||||
const BLOCKS_PER_YEAR: usize = 365 * 24 * 60 * 60 / BLOCK_TIME;
|
||||
#[allow(clippy::as_conversions)]
|
||||
const TIP_APPLICATION: f64 = (LOCK_WINDOW * BLOCK_TIME) as f64;
|
||||
|
||||
// TODO: Expose an API to reset this in case a reorg occurs/the RPC fails/returns garbage
|
||||
|
@ -74,9 +75,11 @@ async fn select_n<'a, R: RngCore + CryptoRng, RPC: RpcConnection>(
|
|||
age -= TIP_APPLICATION;
|
||||
} else {
|
||||
// f64 does not have try_from available, which is why these are written with `as`
|
||||
#[allow(clippy::as_conversions)]
|
||||
age = (rng.next_u64() % u64::try_from(RECENT_WINDOW * BLOCK_TIME).unwrap()) as f64;
|
||||
}
|
||||
|
||||
#[allow(clippy::as_conversions)]
|
||||
let o = (age * per_second) as u64;
|
||||
if o < high {
|
||||
let i = distribution.partition_point(|s| *s < (high - 1 - o));
|
||||
|
@ -141,7 +144,6 @@ pub struct Decoys {
|
|||
}
|
||||
|
||||
impl Decoys {
|
||||
#[must_use]
|
||||
pub fn len(&self) -> usize {
|
||||
self.offsets.len()
|
||||
}
|
||||
|
@ -181,6 +183,7 @@ impl Decoys {
|
|||
let per_second = {
|
||||
let blocks = distribution.len().min(BLOCKS_PER_YEAR);
|
||||
let outputs = high - distribution[distribution.len().saturating_sub(blocks + 1)];
|
||||
#[allow(clippy::as_conversions)]
|
||||
(outputs as f64) / ((blocks * BLOCK_TIME) as f64)
|
||||
};
|
||||
|
||||
|
|
|
@ -124,7 +124,6 @@ impl ExtraField {
|
|||
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
|
||||
pub struct Extra(Vec<ExtraField>);
|
||||
impl Extra {
|
||||
#[must_use]
|
||||
pub fn keys(&self) -> Option<(EdwardsPoint, Option<Vec<EdwardsPoint>>)> {
|
||||
let mut key = None;
|
||||
let mut additional = None;
|
||||
|
@ -141,7 +140,6 @@ impl Extra {
|
|||
key.map(|key| (key, additional))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn payment_id(&self) -> Option<PaymentId> {
|
||||
for field in &self.0 {
|
||||
if let ExtraField::Nonce(data) = field {
|
||||
|
@ -151,7 +149,6 @@ impl Extra {
|
|||
None
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn data(&self) -> Vec<Vec<u8>> {
|
||||
let mut res = vec![];
|
||||
for field in &self.0 {
|
||||
|
@ -201,7 +198,6 @@ impl Extra {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut buf = vec![];
|
||||
self.write(&mut buf).unwrap();
|
||||
|
|
|
@ -141,17 +141,14 @@ pub struct ViewPair {
|
|||
}
|
||||
|
||||
impl ViewPair {
|
||||
#[must_use]
|
||||
pub const fn new(spend: EdwardsPoint, view: Zeroizing<Scalar>) -> Self {
|
||||
Self { spend, view }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn spend(&self) -> EdwardsPoint {
|
||||
self.spend
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn view(&self) -> EdwardsPoint {
|
||||
self.view.deref() * &ED25519_BASEPOINT_TABLE
|
||||
}
|
||||
|
@ -176,7 +173,6 @@ impl ViewPair {
|
|||
}
|
||||
|
||||
/// Returns an address with the provided specification.
|
||||
#[must_use]
|
||||
pub fn address(&self, network: Network, spec: AddressSpec) -> MoneroAddress {
|
||||
let mut spend = self.spend;
|
||||
let mut view: EdwardsPoint = self.view.deref() * &ED25519_BASEPOINT_TABLE;
|
||||
|
@ -254,7 +250,6 @@ impl Scanner {
|
|||
///
|
||||
/// If None is passed, a modified shared key derivation is used which is immune to the burning
|
||||
/// bug (specifically the Guaranteed feature from Featured Addresses).
|
||||
#[must_use]
|
||||
pub fn from_view(pair: ViewPair, burning_bug: Option<HashSet<CompressedEdwardsY>>) -> Self {
|
||||
let mut subaddresses = HashMap::new();
|
||||
subaddresses.insert(pair.spend.compress(), None);
|
||||
|
|
|
@ -32,7 +32,6 @@ impl AbsoluteId {
|
|||
w.write_all(&[self.o])
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = Vec::with_capacity(32 + 1);
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
@ -61,7 +60,6 @@ impl OutputData {
|
|||
w.write_all(&self.commitment.amount.to_le_bytes())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = Vec::with_capacity(32 + 32 + 32 + 8);
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
@ -110,7 +108,6 @@ impl Metadata {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = Vec::with_capacity(1 + 8 + 1);
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
@ -151,22 +148,18 @@ pub struct ReceivedOutput {
|
|||
}
|
||||
|
||||
impl ReceivedOutput {
|
||||
#[must_use]
|
||||
pub const fn key(&self) -> EdwardsPoint {
|
||||
pub fn key(&self) -> EdwardsPoint {
|
||||
self.data.key
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn key_offset(&self) -> Scalar {
|
||||
pub fn key_offset(&self) -> Scalar {
|
||||
self.data.key_offset
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn commitment(&self) -> Commitment {
|
||||
self.data.commitment.clone()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn arbitrary_data(&self) -> &[Vec<u8>] {
|
||||
&self.metadata.arbitrary_data
|
||||
}
|
||||
|
@ -177,7 +170,6 @@ impl ReceivedOutput {
|
|||
self.metadata.write(w)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut serialized = vec![];
|
||||
self.write(&mut serialized).unwrap();
|
||||
|
@ -223,22 +215,18 @@ impl SpendableOutput {
|
|||
Ok(output)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn key(&self) -> EdwardsPoint {
|
||||
pub fn key(&self) -> EdwardsPoint {
|
||||
self.output.key()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn key_offset(&self) -> Scalar {
|
||||
pub fn key_offset(&self) -> Scalar {
|
||||
self.output.key_offset()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn commitment(&self) -> Commitment {
|
||||
self.output.commitment()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn arbitrary_data(&self) -> &[Vec<u8>] {
|
||||
self.output.arbitrary_data()
|
||||
}
|
||||
|
@ -270,8 +258,7 @@ impl<O: Clone + Zeroize> Drop for Timelocked<O> {
|
|||
impl<O: Clone + Zeroize> ZeroizeOnDrop for Timelocked<O> {}
|
||||
|
||||
impl<O: Clone + Zeroize> Timelocked<O> {
|
||||
#[must_use]
|
||||
pub const fn timelock(&self) -> Timelock {
|
||||
pub fn timelock(&self) -> Timelock {
|
||||
self.0
|
||||
}
|
||||
|
||||
|
|
|
@ -7,25 +7,21 @@ use rand_core::{RngCore, CryptoRng};
|
|||
pub(crate) mod classic;
|
||||
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
|
||||
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod seed_error {
|
||||
/// Error when decoding a seed.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
pub enum SeedError {
|
||||
#[cfg_attr(feature = "std", error("invalid number of words in seed"))]
|
||||
InvalidSeedLength,
|
||||
#[cfg_attr(feature = "std", error("unknown language"))]
|
||||
UnknownLanguage,
|
||||
#[cfg_attr(feature = "std", error("invalid checksum"))]
|
||||
InvalidChecksum,
|
||||
#[cfg_attr(feature = "std", error("english old seeds don't support checksums"))]
|
||||
EnglishOldWithChecksum,
|
||||
#[cfg_attr(feature = "std", error("invalid seed"))]
|
||||
InvalidSeed,
|
||||
}
|
||||
/// Error when decoding a seed.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(thiserror::Error))]
|
||||
pub enum SeedError {
|
||||
#[cfg_attr(feature = "std", error("invalid number of words in seed"))]
|
||||
InvalidSeedLength,
|
||||
#[cfg_attr(feature = "std", error("unknown language"))]
|
||||
UnknownLanguage,
|
||||
#[cfg_attr(feature = "std", error("invalid checksum"))]
|
||||
InvalidChecksum,
|
||||
#[cfg_attr(feature = "std", error("english old seeds don't support checksums"))]
|
||||
EnglishOldWithChecksum,
|
||||
#[cfg_attr(feature = "std", error("invalid seed"))]
|
||||
InvalidSeed,
|
||||
}
|
||||
pub use seed_error::SeedError;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum Language {
|
||||
|
@ -61,7 +57,6 @@ impl fmt::Debug for Seed {
|
|||
|
||||
impl Seed {
|
||||
/// Create a new seed.
|
||||
#[must_use]
|
||||
pub fn new<R: RngCore + CryptoRng>(rng: &mut R, lang: Language) -> Self {
|
||||
Self::Classic(ClassicSeed::new(rng, lang))
|
||||
}
|
||||
|
@ -77,7 +72,6 @@ impl Seed {
|
|||
}
|
||||
|
||||
/// Create a Seed from entropy.
|
||||
#[must_use]
|
||||
pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<Self> {
|
||||
ClassicSeed::from_entropy(lang, entropy).map(Self::Classic)
|
||||
}
|
||||
|
@ -90,7 +84,6 @@ impl Seed {
|
|||
}
|
||||
|
||||
/// Return the entropy for this seed.
|
||||
#[must_use]
|
||||
pub fn entropy(&self) -> Zeroizing<[u8; 32]> {
|
||||
match self {
|
||||
Self::Classic(seed) => seed.entropy(),
|
||||
|
|
|
@ -25,7 +25,7 @@ struct SignableTransactionBuilderInternal {
|
|||
impl SignableTransactionBuilderInternal {
|
||||
// Takes in the change address so users don't miss that they have to manually set one
|
||||
// If they don't, all leftover funds will become part of the fee
|
||||
const fn new(protocol: Protocol, fee: Fee, change_address: Option<Change>) -> Self {
|
||||
fn new(protocol: Protocol, fee: Fee, change_address: Option<Change>) -> Self {
|
||||
Self {
|
||||
protocol,
|
||||
fee,
|
||||
|
@ -91,7 +91,6 @@ impl SignableTransactionBuilder {
|
|||
Self(self.0.clone())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn new(protocol: Protocol, fee: Fee, change_address: Option<Change>) -> Self {
|
||||
Self(Arc::new(RwLock::new(SignableTransactionBuilderInternal::new(
|
||||
protocol,
|
||||
|
|
|
@ -211,7 +211,6 @@ pub struct Fee {
|
|||
}
|
||||
|
||||
impl Fee {
|
||||
#[must_use]
|
||||
pub fn calculate(&self, weight: usize) -> u64 {
|
||||
((((self.per_weight * u64::try_from(weight).unwrap()) - 1) / self.mask) + 1) * self.mask
|
||||
}
|
||||
|
@ -262,7 +261,6 @@ impl fmt::Debug for Change {
|
|||
|
||||
impl Change {
|
||||
/// Create a change output specification from a ViewPair, as needed to maintain privacy.
|
||||
#[must_use]
|
||||
pub fn new(view: &ViewPair, guaranteed: bool) -> Self {
|
||||
Self {
|
||||
address: view.address(
|
||||
|
@ -280,7 +278,6 @@ impl Change {
|
|||
/// Create a fingerprintable change output specification which will harm privacy.
|
||||
///
|
||||
/// Only use this if you know what you're doing.
|
||||
#[must_use]
|
||||
pub const fn fingerprintable(address: MoneroAddress) -> Self {
|
||||
Self { address, view: None }
|
||||
}
|
||||
|
@ -394,8 +391,7 @@ impl SignableTransaction {
|
|||
Ok(Self { protocol, r_seed, inputs, payments, data, fee })
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn fee(&self) -> u64 {
|
||||
pub fn fee(&self) -> u64 {
|
||||
self.fee
|
||||
}
|
||||
|
||||
|
@ -568,7 +564,6 @@ impl SignableTransaction {
|
|||
/// The eventuality is defined as the TX extra/outputs this transaction will create, if signed
|
||||
/// with the specified seed. This eventuality can be compared to on-chain transactions to see
|
||||
/// if the transaction has already been signed and published.
|
||||
#[must_use]
|
||||
pub fn eventuality(&self) -> Option<Eventuality> {
|
||||
let inputs = self.inputs.iter().map(SpendableOutput::key).collect::<Vec<_>>();
|
||||
let (tx_key, additional, outputs, id) = Self::prepare_payments(
|
||||
|
@ -726,7 +721,6 @@ impl Eventuality {
|
|||
///
|
||||
/// This extra may be used with a transaction with a distinct set of inputs, yet no honest
|
||||
/// transaction which doesn't satisfy this Eventuality will contain it.
|
||||
#[must_use]
|
||||
pub fn extra(&self) -> &[u8] {
|
||||
&self.extra
|
||||
}
|
||||
|
@ -817,7 +811,6 @@ impl Eventuality {
|
|||
write_vec(write_byte, &self.extra, w)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut buf = Vec::with_capacity(128);
|
||||
self.write(&mut buf).unwrap();
|
||||
|
|
|
@ -82,7 +82,6 @@ impl Default for MemDb {
|
|||
|
||||
impl MemDb {
|
||||
/// Create a new in-memory database.
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
|
|
@ -24,17 +24,14 @@ mod shims {
|
|||
}
|
||||
|
||||
impl Error {
|
||||
#[must_use]
|
||||
pub fn new<E: 'static + Send + Sync>(kind: ErrorKind, error: E) -> Self {
|
||||
Self { kind, error: Box::new(error) }
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn kind(&self) -> ErrorKind {
|
||||
self.kind
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn into_inner(self) -> Option<Box<dyn Send + Sync>> {
|
||||
Some(self.error)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
use core::{ops::Deref, fmt};
|
||||
use std::{io, collections::HashMap};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
|
@ -68,7 +70,7 @@ impl<C: Ciphersuite, M: Message> EncryptionKeyMessage<C, M> {
|
|||
}
|
||||
|
||||
#[cfg(any(test, feature = "tests"))]
|
||||
pub(crate) const fn enc_key(&self) -> C::G {
|
||||
pub(crate) fn enc_key(&self) -> C::G {
|
||||
self.enc_key
|
||||
}
|
||||
}
|
||||
|
@ -328,19 +330,13 @@ fn encryption_key_transcript(context: &str) -> RecommendedTranscript {
|
|||
transcript
|
||||
}
|
||||
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod decryption_error {
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||
pub(crate) enum DecryptionError {
|
||||
#[error("accused provided an invalid signature")]
|
||||
InvalidSignature,
|
||||
#[error("accuser provided an invalid decryption key")]
|
||||
InvalidProof,
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||
pub(crate) enum DecryptionError {
|
||||
#[error("accused provided an invalid signature")]
|
||||
InvalidSignature,
|
||||
#[error("accuser provided an invalid decryption key")]
|
||||
InvalidProof,
|
||||
}
|
||||
pub(crate) use decryption_error::DecryptionError;
|
||||
|
||||
// A simple box for managing encryption.
|
||||
#[derive(Clone)]
|
||||
|
@ -386,7 +382,7 @@ impl<C: Ciphersuite> Encryption<C> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn registration<M: Message>(&self, msg: M) -> EncryptionKeyMessage<C, M> {
|
||||
pub(crate) fn registration<M: Message>(&self, msg: M) -> EncryptionKeyMessage<C, M> {
|
||||
EncryptionKeyMessage { msg, enc_key: self.enc_pub_key }
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ impl<C: Ciphersuite> KeyGenMachine<C> {
|
|||
/// Create a new machine to generate a key.
|
||||
///
|
||||
/// The context string should be unique among multisigs.
|
||||
pub const fn new(params: ThresholdParams, context: String) -> Self {
|
||||
pub fn new(params: ThresholdParams, context: String) -> Self {
|
||||
Self { params, context, curve: PhantomData }
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
use core::fmt::{self, Debug};
|
||||
extern crate alloc;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
|
@ -61,58 +62,49 @@ impl fmt::Display for Participant {
|
|||
}
|
||||
|
||||
/// Various errors possible during key generation.
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod dkg_error {
|
||||
use core::fmt::Debug;
|
||||
use thiserror::Error;
|
||||
use super::Participant;
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(Error))]
|
||||
pub enum DkgError<B: Clone + PartialEq + Eq + Debug> {
|
||||
/// A parameter was zero.
|
||||
#[cfg_attr(feature = "std", error("a parameter was 0 (threshold {0}, participants {1})"))]
|
||||
ZeroParameter(u16, u16),
|
||||
/// The threshold exceeded the amount of participants.
|
||||
#[cfg_attr(feature = "std", error("invalid threshold (max {1}, got {0})"))]
|
||||
InvalidThreshold(u16, u16),
|
||||
/// Invalid participant identifier.
|
||||
#[cfg_attr(
|
||||
feature = "std",
|
||||
error("invalid participant (0 < participant <= {0}, yet participant is {1})")
|
||||
)]
|
||||
InvalidParticipant(u16, Participant),
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "std", derive(Error))]
|
||||
pub enum DkgError<B: Clone + PartialEq + Eq + Debug> {
|
||||
/// A parameter was zero.
|
||||
#[cfg_attr(feature = "std", error("a parameter was 0 (threshold {0}, participants {1})"))]
|
||||
ZeroParameter(u16, u16),
|
||||
/// The threshold exceeded the amount of participants.
|
||||
#[cfg_attr(feature = "std", error("invalid threshold (max {1}, got {0})"))]
|
||||
InvalidThreshold(u16, u16),
|
||||
/// Invalid participant identifier.
|
||||
#[cfg_attr(
|
||||
feature = "std",
|
||||
error("invalid participant (0 < participant <= {0}, yet participant is {1})")
|
||||
)]
|
||||
InvalidParticipant(u16, Participant),
|
||||
/// Invalid signing set.
|
||||
#[cfg_attr(feature = "std", error("invalid signing set"))]
|
||||
InvalidSigningSet,
|
||||
/// Invalid amount of participants.
|
||||
#[cfg_attr(feature = "std", error("invalid participant quantity (expected {0}, got {1})"))]
|
||||
InvalidParticipantQuantity(usize, usize),
|
||||
/// A participant was duplicated.
|
||||
#[cfg_attr(feature = "std", error("duplicated participant ({0})"))]
|
||||
DuplicatedParticipant(Participant),
|
||||
/// A participant was missing.
|
||||
#[cfg_attr(feature = "std", error("missing participant {0}"))]
|
||||
MissingParticipant(Participant),
|
||||
|
||||
/// Invalid signing set.
|
||||
#[cfg_attr(feature = "std", error("invalid signing set"))]
|
||||
InvalidSigningSet,
|
||||
/// Invalid amount of participants.
|
||||
#[cfg_attr(feature = "std", error("invalid participant quantity (expected {0}, got {1})"))]
|
||||
InvalidParticipantQuantity(usize, usize),
|
||||
/// A participant was duplicated.
|
||||
#[cfg_attr(feature = "std", error("duplicated participant ({0})"))]
|
||||
DuplicatedParticipant(Participant),
|
||||
/// A participant was missing.
|
||||
#[cfg_attr(feature = "std", error("missing participant {0}"))]
|
||||
MissingParticipant(Participant),
|
||||
|
||||
/// An invalid proof of knowledge was provided.
|
||||
#[cfg_attr(feature = "std", error("invalid proof of knowledge (participant {0})"))]
|
||||
InvalidProofOfKnowledge(Participant),
|
||||
/// An invalid DKG share was provided.
|
||||
#[cfg_attr(feature = "std", error("invalid share (participant {participant}, blame {blame})"))]
|
||||
InvalidShare { participant: Participant, blame: Option<B> },
|
||||
}
|
||||
/// An invalid proof of knowledge was provided.
|
||||
#[cfg_attr(feature = "std", error("invalid proof of knowledge (participant {0})"))]
|
||||
InvalidProofOfKnowledge(Participant),
|
||||
/// An invalid DKG share was provided.
|
||||
#[cfg_attr(feature = "std", error("invalid share (participant {participant}, blame {blame})"))]
|
||||
InvalidShare { participant: Participant, blame: Option<B> },
|
||||
}
|
||||
pub use dkg_error::DkgError;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod lib {
|
||||
pub use super::*;
|
||||
|
||||
use core::ops::Deref;
|
||||
use alloc::sync::Arc;
|
||||
use std::{io, collections::HashMap};
|
||||
use std::{sync::Arc, io, collections::HashMap};
|
||||
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
|
@ -268,17 +260,17 @@ mod lib {
|
|||
}
|
||||
|
||||
/// Parameters for these keys.
|
||||
pub const fn params(&self) -> ThresholdParams {
|
||||
pub fn params(&self) -> ThresholdParams {
|
||||
self.params
|
||||
}
|
||||
|
||||
/// Secret share for these keys.
|
||||
pub const fn secret_share(&self) -> &Zeroizing<C::F> {
|
||||
pub fn secret_share(&self) -> &Zeroizing<C::F> {
|
||||
&self.secret_share
|
||||
}
|
||||
|
||||
/// Group key for these keys.
|
||||
pub const fn group_key(&self) -> C::G {
|
||||
pub fn group_key(&self) -> C::G {
|
||||
self.group_key
|
||||
}
|
||||
|
||||
|
@ -432,7 +424,7 @@ mod lib {
|
|||
}
|
||||
|
||||
/// Return the current offset in-use for these keys.
|
||||
pub const fn current_offset(&self) -> Option<C::F> {
|
||||
pub fn current_offset(&self) -> Option<C::F> {
|
||||
self.offset
|
||||
}
|
||||
|
||||
|
@ -506,12 +498,12 @@ mod lib {
|
|||
|
||||
impl<C: Ciphersuite> ThresholdView<C> {
|
||||
/// Return the offset for this view.
|
||||
pub const fn offset(&self) -> C::F {
|
||||
pub fn offset(&self) -> C::F {
|
||||
self.offset
|
||||
}
|
||||
|
||||
/// Return the group key.
|
||||
pub const fn group_key(&self) -> C::G {
|
||||
pub fn group_key(&self) -> C::G {
|
||||
self.group_key
|
||||
}
|
||||
|
||||
|
@ -521,7 +513,7 @@ mod lib {
|
|||
}
|
||||
|
||||
/// Return the interpolated, offset secret share.
|
||||
pub const fn secret_share(&self) -> &Zeroizing<C::F> {
|
||||
pub fn secret_share(&self) -> &Zeroizing<C::F> {
|
||||
&self.secret_share
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use core::{marker::PhantomData, ops::Deref};
|
||||
use alloc::sync::Arc;
|
||||
use std::{
|
||||
sync::Arc,
|
||||
io::{self, Read, Write},
|
||||
collections::HashMap,
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@ impl<G0: PrimeGroup, G1: PrimeGroup> Re<G0, G1> {
|
|||
Self::R(G0::identity(), G1::identity())
|
||||
}
|
||||
|
||||
pub(crate) const fn e_default() -> Self {
|
||||
pub(crate) fn e_default() -> Self {
|
||||
Self::e(G0::Scalar::ZERO)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ pub(crate) enum BitSignature {
|
|||
}
|
||||
|
||||
impl BitSignature {
|
||||
pub(crate) const fn to_u8(&self) -> u8 {
|
||||
pub(crate) fn to_u8(&self) -> u8 {
|
||||
match self {
|
||||
Self::ClassicLinear => 0,
|
||||
Self::ConciseLinear => 1,
|
||||
|
@ -35,7 +35,7 @@ impl BitSignature {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn from(algorithm: u8) -> Self {
|
||||
pub(crate) fn from(algorithm: u8) -> Self {
|
||||
match algorithm {
|
||||
0 => Self::ClassicLinear,
|
||||
1 => Self::ConciseLinear,
|
||||
|
@ -45,14 +45,14 @@ impl BitSignature {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn bits(&self) -> usize {
|
||||
pub(crate) fn bits(&self) -> usize {
|
||||
match self {
|
||||
Self::ClassicLinear | Self::EfficientLinear => 1,
|
||||
Self::ConciseLinear | Self::CompromiseLinear => 2,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const fn ring_len(&self) -> usize {
|
||||
pub(crate) fn ring_len(&self) -> usize {
|
||||
#[allow(clippy::as_conversions, clippy::cast_possible_truncation)] // Needed for const
|
||||
2_usize.pow(self.bits() as u32)
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@ use core::ops::{Deref, DerefMut};
|
|||
#[cfg(feature = "serialize")]
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
use thiserror::Error;
|
||||
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use digest::{Digest, HashMarker};
|
||||
|
||||
|
@ -92,27 +93,21 @@ impl<G: PrimeGroup> Generators<G> {
|
|||
}
|
||||
|
||||
/// Error for cross-group DLEq proofs.
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod dleq_error {
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, PartialEq, Eq, Debug)]
|
||||
pub enum DLEqError {
|
||||
/// Invalid proof of knowledge.
|
||||
#[error("invalid proof of knowledge")]
|
||||
InvalidProofOfKnowledge,
|
||||
/// Invalid proof length.
|
||||
#[error("invalid proof length")]
|
||||
InvalidProofLength,
|
||||
/// Invalid challenge.
|
||||
#[error("invalid challenge")]
|
||||
InvalidChallenge,
|
||||
/// Invalid proof.
|
||||
#[error("invalid proof")]
|
||||
InvalidProof,
|
||||
}
|
||||
#[derive(Error, PartialEq, Eq, Debug)]
|
||||
pub enum DLEqError {
|
||||
/// Invalid proof of knowledge.
|
||||
#[error("invalid proof of knowledge")]
|
||||
InvalidProofOfKnowledge,
|
||||
/// Invalid proof length.
|
||||
#[error("invalid proof length")]
|
||||
InvalidProofLength,
|
||||
/// Invalid challenge.
|
||||
#[error("invalid challenge")]
|
||||
InvalidChallenge,
|
||||
/// Invalid proof.
|
||||
#[error("invalid proof")]
|
||||
InvalidProof,
|
||||
}
|
||||
pub use dleq_error::DLEqError;
|
||||
|
||||
// This should never be directly instantiated and uses a u8 to represent internal values
|
||||
// Any external usage is likely invalid
|
||||
|
|
|
@ -147,7 +147,7 @@ pub type IetfSchnorr<C, H> = Schnorr<C, IetfTranscript, H>;
|
|||
|
||||
impl<C: Curve, T: Sync + Clone + Debug + Transcript, H: Hram<C>> Schnorr<C, T, H> {
|
||||
/// Construct a Schnorr algorithm continuing the specified transcript.
|
||||
pub const fn new(transcript: T) -> Self {
|
||||
pub fn new(transcript: T) -> Self {
|
||||
Self { transcript, c: None, _hram: PhantomData }
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ impl<C: Curve, H: Hram<C>> IetfSchnorr<C, H> {
|
|||
/// Construct a IETF-compatible Schnorr algorithm.
|
||||
///
|
||||
/// Please see the `IetfSchnorr` documentation for the full details of this.
|
||||
pub const fn ietf() -> Self {
|
||||
pub fn ietf() -> Self {
|
||||
Self::new(IetfTranscript(vec![]))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use core::fmt::Debug;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// Distributed key generation protocol.
|
||||
pub use dkg::{self, Participant, ThresholdParams, ThresholdCore, ThresholdKeys, ThresholdView};
|
||||
|
||||
|
@ -20,32 +23,25 @@ pub mod sign;
|
|||
#[cfg(any(test, feature = "tests"))]
|
||||
pub mod tests;
|
||||
|
||||
#[allow(clippy::std_instead_of_core)]
|
||||
mod frost_error {
|
||||
use core::fmt::Debug;
|
||||
use thiserror::Error;
|
||||
use dkg::Participant;
|
||||
/// Various errors possible during signing.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||
pub enum FrostError {
|
||||
#[error("invalid participant (0 < participant <= {0}, yet participant is {1})")]
|
||||
InvalidParticipant(u16, Participant),
|
||||
#[error("invalid signing set ({0})")]
|
||||
InvalidSigningSet(&'static str),
|
||||
#[error("invalid participant quantity (expected {0}, got {1})")]
|
||||
InvalidParticipantQuantity(usize, usize),
|
||||
#[error("duplicated participant ({0})")]
|
||||
DuplicatedParticipant(Participant),
|
||||
#[error("missing participant {0}")]
|
||||
MissingParticipant(Participant),
|
||||
/// Various errors possible during signing.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
|
||||
pub enum FrostError {
|
||||
#[error("invalid participant (0 < participant <= {0}, yet participant is {1})")]
|
||||
InvalidParticipant(u16, Participant),
|
||||
#[error("invalid signing set ({0})")]
|
||||
InvalidSigningSet(&'static str),
|
||||
#[error("invalid participant quantity (expected {0}, got {1})")]
|
||||
InvalidParticipantQuantity(usize, usize),
|
||||
#[error("duplicated participant ({0})")]
|
||||
DuplicatedParticipant(Participant),
|
||||
#[error("missing participant {0}")]
|
||||
MissingParticipant(Participant),
|
||||
|
||||
#[error("invalid preprocess (participant {0})")]
|
||||
InvalidPreprocess(Participant),
|
||||
#[error("invalid share (participant {0})")]
|
||||
InvalidShare(Participant),
|
||||
}
|
||||
#[error("invalid preprocess (participant {0})")]
|
||||
InvalidPreprocess(Participant),
|
||||
#[error("invalid share (participant {0})")]
|
||||
InvalidShare(Participant),
|
||||
}
|
||||
pub use frost_error::FrostError;
|
||||
|
||||
/// Validate a map of values to have the expected participants.
|
||||
pub fn validate_map<T>(
|
||||
|
|
|
@ -53,7 +53,7 @@ struct Params<C: Curve, A: Algorithm<C>> {
|
|||
}
|
||||
|
||||
impl<C: Curve, A: Algorithm<C>> Params<C, A> {
|
||||
const fn new(algorithm: A, keys: ThresholdKeys<C>) -> Self {
|
||||
fn new(algorithm: A, keys: ThresholdKeys<C>) -> Self {
|
||||
Self { algorithm, keys }
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ pub struct AlgorithmMachine<C: Curve, A: Algorithm<C>> {
|
|||
|
||||
impl<C: Curve, A: Algorithm<C>> AlgorithmMachine<C, A> {
|
||||
/// Creates a new machine to generate a signature with the specified keys.
|
||||
pub const fn new(algorithm: A, keys: ThresholdKeys<C>) -> Self {
|
||||
pub fn new(algorithm: A, keys: ThresholdKeys<C>) -> Self {
|
||||
Self { params: Params::new(algorithm, keys) }
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ Pippenger 6 is more efficient at 250 with 655µs per
|
|||
Pippenger 7 is more efficient at 475 with 500µs per
|
||||
Pippenger 8 is more efficient at 875 with 499µs per
|
||||
*/
|
||||
const fn algorithm(len: usize) -> Algorithm {
|
||||
fn algorithm(len: usize) -> Algorithm {
|
||||
#[cfg(not(debug_assertions))]
|
||||
if len == 0 {
|
||||
Algorithm::Null
|
||||
|
|
|
@ -61,7 +61,7 @@ enum DigestTranscriptMember {
|
|||
}
|
||||
|
||||
impl DigestTranscriptMember {
|
||||
const fn as_u8(&self) -> u8 {
|
||||
fn as_u8(&self) -> u8 {
|
||||
match self {
|
||||
Self::Name => 0,
|
||||
Self::Domain => 1,
|
||||
|
|
Loading…
Reference in a new issue