Refine from pedantic, remove erratic consts

This commit is contained in:
Luke Parker
2023-07-08 01:26:08 -04:00
parent 286e96ccd8
commit 3ca76c51e4
36 changed files with 192 additions and 335 deletions

View File

@@ -1,42 +1,26 @@
# No warnings allowed # No warnings allowed
-D warnings -D warnings
# Non-default groups # nursery
-D clippy::nursery -D clippy::nursery
-D clippy::pedantic # Erratic and unhelpful
-A clippy::missing_const_for_fn
# Not worth the effort
-A clippy::implicit_hasher
# Stylistic preferrence
-A clippy::option_if_let_else
# Too many false/irrelevant positives # Too many false/irrelevant positives
-A clippy::redundant_pub_crate -A clippy::redundant_pub_crate
-A clippy::similar_names
# Flags on any debug_assert using an RNG # Flags on any debug_assert using an RNG
-A clippy::debug_assert_with_mut_call -A clippy::debug_assert_with_mut_call
# Stylistic preference
-A clippy::option_if_let_else
# Frequently used # pedantic
-A clippy::large_types_passed_by_value -D clippy::unnecessary_wraps
-A clippy::wildcard_imports -D clippy::unused_async
-A clippy::too_many_lines -D clippy::unused_self
# Used to avoid doing &* on copy-able items, with the * being the concern # restrictions
-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
# Safety # Safety
-D clippy::as_conversions -D clippy::as_conversions
-D clippy::float_cmp_const
-D clippy::disallowed_script_idents -D clippy::disallowed_script_idents
-D clippy::wildcard_enum_match_arm -D clippy::wildcard_enum_match_arm
@@ -54,19 +38,10 @@
-D clippy::format_push_string -D clippy::format_push_string
-D clippy::string_to_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 # These potentially should be enabled in the future
-A clippy::missing_errors_doc # -D clippy::missing_errors_doc
-A clippy::missing_panics_doc # -D clippy::missing_panics_doc
-A clippy::doc_markdown # -D clippy::doc_markdown
# TODO: Enable this # TODO: Enable this
# -D clippy::cargo # -D clippy::cargo

View File

@@ -9,7 +9,6 @@ use crate::hash;
/// Monero's hash to point function, as named `ge_fromfe_frombytes_vartime`. /// Monero's hash to point function, as named `ge_fromfe_frombytes_vartime`.
#[allow(clippy::many_single_char_names)] #[allow(clippy::many_single_char_names)]
#[must_use]
pub fn hash_to_point(bytes: [u8; 32]) -> EdwardsPoint { pub fn hash_to_point(bytes: [u8; 32]) -> EdwardsPoint {
#[allow(non_snake_case, clippy::unreadable_literal)] #[allow(non_snake_case, clippy::unreadable_literal)]
let A = FieldElement::from(486662u64); let A = FieldElement::from(486662u64);

View File

@@ -61,7 +61,6 @@ pub struct Generators {
} }
/// Generate generators as needed for Bulletproofs(+), as Monero does. /// Generate generators as needed for Bulletproofs(+), as Monero does.
#[must_use]
pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators { pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators {
let mut res = let mut res =
Generators { G: [EdwardsPoint::identity(); MAX_MN], H: [EdwardsPoint::identity(); MAX_MN] }; Generators { G: [EdwardsPoint::identity(); MAX_MN], H: [EdwardsPoint::identity(); MAX_MN] };

View File

@@ -33,7 +33,6 @@ impl BlockHeader {
w.write_all(&self.nonce.to_le_bytes()) w.write_all(&self.nonce.to_le_bytes())
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![]; let mut serialized = vec![];
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();
@@ -59,7 +58,6 @@ pub struct Block {
} }
impl Block { impl Block {
#[must_use]
pub fn number(&self) -> usize { pub fn number(&self) -> usize {
match self.miner_tx.prefix.inputs.get(0) { match self.miner_tx.prefix.inputs.get(0) {
Some(Input::Gen(number)) => (*number).try_into().unwrap(), Some(Input::Gen(number)) => (*number).try_into().unwrap(),
@@ -93,7 +91,6 @@ impl Block {
out out
} }
#[must_use]
pub fn hash(&self) -> [u8; 32] { pub fn hash(&self) -> [u8; 32] {
let hash = hash(&self.serialize_hashable()); let hash = hash(&self.serialize_hashable());
if hash == CORRECT_BLOCK_HASH_202612 { if hash == CORRECT_BLOCK_HASH_202612 {
@@ -103,7 +100,6 @@ impl Block {
hash hash
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![]; let mut serialized = vec![];
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();

View File

@@ -60,7 +60,6 @@ pub enum Protocol {
impl Protocol { impl Protocol {
/// Amount of ring members under this protocol version. /// Amount of ring members under this protocol version.
#[must_use]
pub const fn ring_len(&self) -> usize { pub const fn ring_len(&self) -> usize {
match self { match self {
Self::v14 => 11, Self::v14 => 11,
@@ -72,7 +71,6 @@ impl Protocol {
/// Whether or not the specified version uses Bulletproofs or Bulletproofs+. /// 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. /// This method will likely be reworked when versions not using Bulletproofs at all are added.
#[must_use]
pub const fn bp_plus(&self) -> bool { pub const fn bp_plus(&self) -> bool {
match self { match self {
Self::v14 => false, Self::v14 => false,
@@ -82,7 +80,6 @@ impl Protocol {
} }
// TODO: Make this an Option when we support pre-RCT protocols // TODO: Make this an Option when we support pre-RCT protocols
#[must_use]
pub const fn optimal_rct_type(&self) -> RctType { pub const fn optimal_rct_type(&self) -> RctType {
match self { match self {
Self::v14 => RctType::Clsag, Self::v14 => RctType::Clsag,
@@ -144,25 +141,21 @@ pub struct Commitment {
impl Commitment { impl Commitment {
/// A commitment to zero, defined with a mask of 1 (as to not be the identity). /// A commitment to zero, defined with a mask of 1 (as to not be the identity).
#[must_use]
pub fn zero() -> Self { pub fn zero() -> Self {
Self { mask: Scalar::one(), amount: 0 } Self { mask: Scalar::one(), amount: 0 }
} }
#[must_use] pub fn new(mask: Scalar, amount: u64) -> Self {
pub const fn new(mask: Scalar, amount: u64) -> Self {
Self { mask, amount } Self { mask, amount }
} }
/// Calculate a Pedersen commitment, as a point, from the transparent structure. /// Calculate a Pedersen commitment, as a point, from the transparent structure.
#[must_use]
pub fn calculate(&self) -> EdwardsPoint { pub fn calculate(&self) -> EdwardsPoint {
(&self.mask * &ED25519_BASEPOINT_TABLE) + (Scalar::from(self.amount) * H()) (&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. /// 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 { pub fn random_scalar<R: RngCore + CryptoRng>(rng: &mut R) -> Scalar {
let mut r = [0; 64]; let mut r = [0; 64];
rng.fill_bytes(&mut r); 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. /// Hash the provided data to a scalar via keccak256(data) % l.
#[must_use]
pub fn hash_to_scalar(data: &[u8]) -> Scalar { pub fn hash_to_scalar(data: &[u8]) -> Scalar {
let scalar = Scalar::from_bytes_mod_order(hash(data)); let scalar = Scalar::from_bytes_mod_order(hash(data));
// Monero will explicitly error in this case // Monero will explicitly error in this case

View File

@@ -2,7 +2,6 @@ use std_shims::vec::Vec;
use crate::hash; use crate::hash;
#[must_use]
pub(crate) fn merkle_root(root: [u8; 32], leafs: &[[u8; 32]]) -> [u8; 32] { pub(crate) fn merkle_root(root: [u8; 32], leafs: &[[u8; 32]]) -> [u8; 32] {
match leafs.len() { match leafs.len() {
0 => root, 0 => root,

View File

@@ -56,7 +56,7 @@ pub(crate) fn hash_cache(cache: &mut Scalar, mash: &[[u8; 32]]) -> Scalar {
*cache *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 logM = 0;
let mut M; let mut M;
while { while {

View File

@@ -140,7 +140,6 @@ impl Bulletproofs {
self.write_core(w, |points, w| write_vec(write_point, points, w)) self.write_core(w, |points, w| write_vec(write_point, points, w))
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![]; let mut serialized = vec![];
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();

View File

@@ -6,10 +6,9 @@ use std_shims::{
io::{self, Read, Write}, io::{self, Read, Write},
}; };
use rand_core::{RngCore, CryptoRng};
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing}; use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
use subtle::{ConstantTimeEq, Choice, CtOption}; use subtle::{ConstantTimeEq, Choice, CtOption};
use rand_core::{RngCore, CryptoRng};
use curve25519_dalek::{ use curve25519_dalek::{
constants::ED25519_BASEPOINT_TABLE, constants::ED25519_BASEPOINT_TABLE,
@@ -30,31 +29,27 @@ pub use multisig::{ClsagDetails, ClsagAddendum, ClsagMultisig};
#[cfg(feature = "multisig")] #[cfg(feature = "multisig")]
pub(crate) use multisig::add_key_image_share; pub(crate) use multisig::add_key_image_share;
#[allow(clippy::std_instead_of_core)] /// Errors returned when CLSAG signing fails.
mod clsag_error { #[derive(Clone, Copy, PartialEq, Eq, Debug)]
/// Errors returned when CLSAG signing fails. #[cfg_attr(feature = "std", derive(thiserror::Error))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum ClsagError {
#[cfg_attr(feature = "std", derive(thiserror::Error))] #[cfg_attr(feature = "std", error("internal error ({0})"))]
pub enum ClsagError { InternalError(&'static str),
#[cfg_attr(feature = "std", error("internal error ({0})"))] #[cfg_attr(feature = "std", error("invalid ring"))]
InternalError(&'static str), InvalidRing,
#[cfg_attr(feature = "std", error("invalid ring"))] #[cfg_attr(feature = "std", error("invalid ring member (member {0}, ring size {1})"))]
InvalidRing, InvalidRingMember(u8, u8),
#[cfg_attr(feature = "std", error("invalid ring member (member {0}, ring size {1})"))] #[cfg_attr(feature = "std", error("invalid commitment"))]
InvalidRingMember(u8, u8), InvalidCommitment,
#[cfg_attr(feature = "std", error("invalid commitment"))] #[cfg_attr(feature = "std", error("invalid key image"))]
InvalidCommitment, InvalidImage,
#[cfg_attr(feature = "std", error("invalid key image"))] #[cfg_attr(feature = "std", error("invalid D"))]
InvalidImage, InvalidD,
#[cfg_attr(feature = "std", error("invalid D"))] #[cfg_attr(feature = "std", error("invalid s"))]
InvalidD, InvalidS,
#[cfg_attr(feature = "std", error("invalid s"))] #[cfg_attr(feature = "std", error("invalid c1"))]
InvalidS, InvalidC1,
#[cfg_attr(feature = "std", error("invalid c1"))]
InvalidC1,
}
} }
pub use clsag_error::ClsagError;
/// Input being signed for. /// Input being signed for.
#[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)] #[derive(Clone, PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)]
@@ -239,7 +234,6 @@ impl Clsag {
/// Generate CLSAG signatures for the given inputs. /// Generate CLSAG signatures for the given inputs.
/// inputs is of the form (private key, key image, input). /// inputs is of the form (private key, key image, input).
/// sum_outputs is for the sum of the outputs' commitment masks. /// sum_outputs is for the sum of the outputs' commitment masks.
#[must_use]
pub fn sign<R: RngCore + CryptoRng>( pub fn sign<R: RngCore + CryptoRng>(
rng: &mut R, rng: &mut R,
mut inputs: Vec<(Zeroizing<Scalar>, EdwardsPoint, ClsagInput)>, mut inputs: Vec<(Zeroizing<Scalar>, EdwardsPoint, ClsagInput)>,
@@ -249,11 +243,12 @@ impl Clsag {
let mut res = Vec::with_capacity(inputs.len()); let mut res = Vec::with_capacity(inputs.len());
let mut sum_pseudo_outs = Scalar::zero(); let mut sum_pseudo_outs = Scalar::zero();
for i in 0 .. inputs.len() { for i in 0 .. inputs.len() {
let mut mask = random_scalar(rng); let mask = if i == (inputs.len() - 1) {
if i == (inputs.len() - 1) { sum_outputs - sum_pseudo_outs
mask = sum_outputs - sum_pseudo_outs;
} else { } else {
let mask = random_scalar(rng);
sum_pseudo_outs += mask; sum_pseudo_outs += mask;
mask
} }
let mut nonce = Zeroizing::new(random_scalar(rng)); let mut nonce = Zeroizing::new(random_scalar(rng));
@@ -314,7 +309,7 @@ impl Clsag {
Ok(()) 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 (ring_len * 32) + 32 + 32
} }

View File

@@ -68,7 +68,6 @@ pub struct ClsagDetails {
} }
impl ClsagDetails { impl ClsagDetails {
#[must_use]
pub fn new(input: ClsagInput, mask: Scalar) -> Self { pub fn new(input: ClsagInput, mask: Scalar) -> Self {
Self { input, mask } Self { input, mask }
} }
@@ -116,7 +115,6 @@ pub struct ClsagMultisig {
} }
impl ClsagMultisig { impl ClsagMultisig {
#[must_use]
pub fn new( pub fn new(
transcript: RecommendedTranscript, transcript: RecommendedTranscript,
output_key: EdwardsPoint, output_key: EdwardsPoint,

View File

@@ -3,7 +3,6 @@ use curve25519_dalek::edwards::EdwardsPoint;
pub use monero_generators::{hash_to_point as raw_hash_to_point}; pub use monero_generators::{hash_to_point as raw_hash_to_point};
/// Monero's hash to point function, as named `ge_fromfe_frombytes_vartime`. /// Monero's hash to point function, as named `ge_fromfe_frombytes_vartime`.
#[must_use]
pub fn hash_to_point(key: EdwardsPoint) -> EdwardsPoint { pub fn hash_to_point(key: EdwardsPoint) -> EdwardsPoint {
raw_hash_to_point(key.compress().to_bytes()) raw_hash_to_point(key.compress().to_bytes())
} }

View File

@@ -27,7 +27,6 @@ use crate::{
}; };
/// Generate a key image for a given key. Defined as `x * hash_to_point(xG)`. /// 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 { pub fn generate_key_image(secret: &Zeroizing<Scalar>) -> EdwardsPoint {
hash_to_point(&ED25519_BASEPOINT_TABLE * secret.deref()) * secret.deref() hash_to_point(&ED25519_BASEPOINT_TABLE * secret.deref()) * secret.deref()
} }
@@ -78,8 +77,7 @@ pub enum RctType {
} }
impl RctType { impl RctType {
#[must_use] pub fn to_byte(self) -> u8 {
pub const fn to_byte(self) -> u8 {
match self { match self {
Self::Null => 0, Self::Null => 0,
Self::MlsagAggregate => 1, Self::MlsagAggregate => 1,
@@ -91,7 +89,6 @@ impl RctType {
} }
} }
#[must_use]
pub fn from_byte(byte: u8) -> Option<Self> { pub fn from_byte(byte: u8) -> Option<Self> {
Some(match byte { Some(match byte {
0 => Self::Null, 0 => Self::Null,
@@ -105,8 +102,7 @@ impl RctType {
}) })
} }
#[must_use] pub fn compact_encrypted_amounts(&self) -> bool {
pub const fn compact_encrypted_amounts(&self) -> bool {
match self { match self {
Self::Null | Self::MlsagAggregate | Self::MlsagIndividual | Self::Bulletproofs => false, Self::Null | Self::MlsagAggregate | Self::MlsagIndividual | Self::Bulletproofs => false,
Self::BulletproofsCompactAmount | Self::Clsag | Self::BulletproofsPlus => true, Self::BulletproofsCompactAmount | Self::Clsag | Self::BulletproofsPlus => true,
@@ -123,7 +119,7 @@ pub struct RctBase {
} }
impl 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)) 1 + 8 + (outputs * (8 + 32))
} }
@@ -245,7 +241,6 @@ impl RctPrunable {
} }
} }
#[must_use]
pub fn serialize(&self, rct_type: RctType) -> Vec<u8> { pub fn serialize(&self, rct_type: RctType) -> Vec<u8> {
let mut serialized = vec![]; let mut serialized = vec![];
self.write(&mut serialized, rct_type).unwrap(); self.write(&mut serialized, rct_type).unwrap();
@@ -312,7 +307,6 @@ pub struct RctSignatures {
impl RctSignatures { impl RctSignatures {
/// RctType for a given RctSignatures struct. /// RctType for a given RctSignatures struct.
#[must_use]
pub fn rct_type(&self) -> RctType { pub fn rct_type(&self) -> RctType {
match &self.prunable { match &self.prunable {
RctPrunable::Null => RctType::Null, RctPrunable::Null => RctType::Null,
@@ -376,7 +370,6 @@ impl RctSignatures {
self.prunable.write(w, rct_type) self.prunable.write(w, rct_type)
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![]; let mut serialized = vec![];
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();

View File

@@ -47,31 +47,26 @@ struct TransactionsResponse {
txs: Vec<TransactionResponse>, txs: Vec<TransactionResponse>,
} }
#[allow(clippy::std_instead_of_core)] #[derive(Clone, PartialEq, Eq, Debug)]
mod rpc_error { #[cfg_attr(feature = "std", derive(thiserror::Error))]
use std_shims::{vec::Vec, string::String}; pub enum RpcError {
#[derive(Clone, PartialEq, Eq, Debug)] #[cfg_attr(feature = "std", error("internal error ({0})"))]
#[cfg_attr(feature = "std", derive(thiserror::Error))] InternalError(&'static str),
pub enum RpcError { #[cfg_attr(feature = "std", error("connection error"))]
#[cfg_attr(feature = "std", error("internal error ({0})"))] ConnectionError,
InternalError(&'static str), #[cfg_attr(feature = "std", error("invalid node"))]
#[cfg_attr(feature = "std", error("connection error"))] InvalidNode,
ConnectionError, #[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))]
#[cfg_attr(feature = "std", error("invalid node"))] UnsupportedProtocol(usize),
InvalidNode, #[cfg_attr(feature = "std", error("transactions not found"))]
#[cfg_attr(feature = "std", error("unsupported protocol version ({0})"))] TransactionsNotFound(Vec<[u8; 32]>),
UnsupportedProtocol(usize), #[cfg_attr(feature = "std", error("invalid point ({0})"))]
#[cfg_attr(feature = "std", error("transactions not found"))] InvalidPoint(String),
TransactionsNotFound(Vec<[u8; 32]>), #[cfg_attr(feature = "std", error("pruned transaction"))]
#[cfg_attr(feature = "std", error("invalid point ({0})"))] PrunedTransaction,
InvalidPoint(String), #[cfg_attr(feature = "std", error("invalid transaction ({0:?})"))]
#[cfg_attr(feature = "std", error("pruned transaction"))] InvalidTransaction([u8; 32]),
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> { fn rpc_hex(value: &str) -> Result<Vec<u8>, RpcError> {
hex::decode(value).map_err(|_| RpcError::InvalidNode) hex::decode(value).map_err(|_| RpcError::InvalidNode)

View File

@@ -25,7 +25,7 @@ pub enum Input {
impl Input { impl Input {
// Worst-case predictive len // 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 amount due to amount being 0
// Uses 1 byte for the VarInt encoding of the length of the ring as well // Uses 1 byte for the VarInt encoding of the length of the ring as well
1 + 1 + 1 + (8 * ring_len) + 32 1 + 1 + 1 + (8 * ring_len) + 32
@@ -47,7 +47,6 @@ impl Input {
} }
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut res = vec![]; let mut res = vec![];
self.write(&mut res).unwrap(); self.write(&mut res).unwrap();
@@ -82,7 +81,7 @@ pub struct Output {
} }
impl Output { impl Output {
pub(crate) const fn fee_weight() -> usize { pub(crate) fn fee_weight() -> usize {
1 + 1 + 32 + 1 1 + 1 + 32 + 1
} }
@@ -96,7 +95,6 @@ impl Output {
Ok(()) Ok(())
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(8 + 1 + 32); let mut res = Vec::with_capacity(8 + 1 + 32);
self.write(&mut res).unwrap(); self.write(&mut res).unwrap();
@@ -202,7 +200,6 @@ impl TransactionPrefix {
w.write_all(&self.extra) w.write_all(&self.extra)
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut res = vec![]; let mut res = vec![];
self.write(&mut res).unwrap(); self.write(&mut res).unwrap();
@@ -235,7 +232,6 @@ impl TransactionPrefix {
Ok(prefix) Ok(prefix)
} }
#[must_use]
pub fn hash(&self) -> [u8; 32] { pub fn hash(&self) -> [u8; 32] {
hash(&self.serialize()) hash(&self.serialize())
} }
@@ -277,7 +273,6 @@ impl Transaction {
} }
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut res = Vec::with_capacity(2048); let mut res = Vec::with_capacity(2048);
self.write(&mut res).unwrap(); self.write(&mut res).unwrap();
@@ -336,7 +331,6 @@ impl Transaction {
Ok(Self { prefix, signatures, rct_signatures }) Ok(Self { prefix, signatures, rct_signatures })
} }
#[must_use]
pub fn hash(&self) -> [u8; 32] { pub fn hash(&self) -> [u8; 32] {
let mut buf = Vec::with_capacity(2048); let mut buf = Vec::with_capacity(2048);
if self.prefix.version == 1 { if self.prefix.version == 1 {
@@ -365,7 +359,6 @@ impl Transaction {
} }
/// Calculate the hash of this transaction as needed for signing it. /// Calculate the hash of this transaction as needed for signing it.
#[must_use]
pub fn signature_hash(&self) -> [u8; 32] { pub fn signature_hash(&self) -> [u8; 32] {
let mut buf = Vec::with_capacity(2048); let mut buf = Vec::with_capacity(2048);
let mut sig_hash = Vec::with_capacity(96); let mut sig_hash = Vec::with_capacity(96);

View File

@@ -32,7 +32,6 @@ pub struct SubaddressIndex {
} }
impl SubaddressIndex { impl SubaddressIndex {
#[must_use]
pub const fn new(account: u32, address: u32) -> Option<Self> { pub const fn new(account: u32, address: u32) -> Option<Self> {
if (account == 0) && (address == 0) { if (account == 0) && (address == 0) {
return None; return None;
@@ -40,12 +39,10 @@ impl SubaddressIndex {
Some(Self { account, address }) Some(Self { account, address })
} }
#[must_use]
pub const fn account(&self) -> u32 { pub const fn account(&self) -> u32 {
self.account self.account
} }
#[must_use]
pub const fn address(&self) -> u32 { pub const fn address(&self) -> u32 {
self.address self.address
} }
@@ -61,12 +58,10 @@ pub enum AddressSpec {
} }
impl AddressType { impl AddressType {
#[must_use]
pub const fn is_subaddress(&self) -> bool { pub const fn is_subaddress(&self) -> bool {
matches!(self, Self::Subaddress) || matches!(self, Self::Featured { subaddress: true, .. }) matches!(self, Self::Subaddress) || matches!(self, Self::Featured { subaddress: true, .. })
} }
#[must_use]
pub const fn payment_id(&self) -> Option<[u8; 8]> { pub const fn payment_id(&self) -> Option<[u8; 8]> {
if let Self::Integrated(id) = self { if let Self::Integrated(id) = self {
Some(*id) Some(*id)
@@ -77,7 +72,6 @@ impl AddressType {
} }
} }
#[must_use]
pub const fn is_guaranteed(&self) -> bool { pub const fn is_guaranteed(&self) -> bool {
matches!(self, Self::Featured { guaranteed: true, .. }) matches!(self, Self::Featured { guaranteed: true, .. })
} }
@@ -147,7 +141,6 @@ impl<B: AddressBytes> AddressMeta<B> {
} }
/// Create an address's metadata. /// Create an address's metadata.
#[must_use]
pub const fn new(network: Network, kind: AddressType) -> Self { pub const fn new(network: Network, kind: AddressType) -> Self {
Self { _bytes: PhantomData, network, kind } Self { _bytes: PhantomData, network, kind }
} }
@@ -174,17 +167,14 @@ impl<B: AddressBytes> AddressMeta<B> {
meta.ok_or(AddressError::InvalidByte) meta.ok_or(AddressError::InvalidByte)
} }
#[must_use]
pub const fn is_subaddress(&self) -> bool { pub const fn is_subaddress(&self) -> bool {
self.kind.is_subaddress() self.kind.is_subaddress()
} }
#[must_use]
pub const fn payment_id(&self) -> Option<[u8; 8]> { pub const fn payment_id(&self) -> Option<[u8; 8]> {
self.kind.payment_id() self.kind.payment_id()
} }
#[must_use]
pub const fn is_guaranteed(&self) -> bool { pub const fn is_guaranteed(&self) -> bool {
self.kind.is_guaranteed() self.kind.is_guaranteed()
} }
@@ -225,7 +215,6 @@ impl<B: AddressBytes> ToString for Address<B> {
} }
impl<B: AddressBytes> Address<B> { impl<B: AddressBytes> Address<B> {
#[must_use]
pub const fn new(meta: AddressMeta<B>, spend: EdwardsPoint, view: EdwardsPoint) -> Self { pub const fn new(meta: AddressMeta<B>, spend: EdwardsPoint, view: EdwardsPoint) -> Self {
Self { meta, spend, view } Self { meta, spend, view }
} }
@@ -290,22 +279,18 @@ impl<B: AddressBytes> Address<B> {
}) })
} }
#[must_use]
pub const fn network(&self) -> Network { pub const fn network(&self) -> Network {
self.meta.network self.meta.network
} }
#[must_use]
pub const fn is_subaddress(&self) -> bool { pub const fn is_subaddress(&self) -> bool {
self.meta.is_subaddress() self.meta.is_subaddress()
} }
#[must_use]
pub const fn payment_id(&self) -> Option<[u8; 8]> { pub const fn payment_id(&self) -> Option<[u8; 8]> {
self.meta.payment_id() self.meta.payment_id()
} }
#[must_use]
pub const fn is_guaranteed(&self) -> bool { pub const fn is_guaranteed(&self) -> bool {
self.meta.is_guaranteed() 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 // 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. // rest of this library. Doesn't use From as it was conflicting with From<T> for T.
impl MoneroAddress { impl MoneroAddress {
#[must_use]
pub const fn from<B: AddressBytes>(address: Address<B>) -> Self { pub const fn from<B: AddressBytes>(address: Address<B>) -> Self {
Self::new( Self::new(
AddressMeta::new(address.meta.network, address.meta.kind), AddressMeta::new(address.meta.network, address.meta.kind),

View File

@@ -24,6 +24,7 @@ const MATURITY: u64 = 60;
const RECENT_WINDOW: usize = 15; const RECENT_WINDOW: usize = 15;
const BLOCK_TIME: usize = 120; const BLOCK_TIME: usize = 120;
const BLOCKS_PER_YEAR: usize = 365 * 24 * 60 * 60 / BLOCK_TIME; 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; 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 // 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; age -= TIP_APPLICATION;
} else { } else {
// f64 does not have try_from available, which is why these are written with `as` // 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; 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; let o = (age * per_second) as u64;
if o < high { if o < high {
let i = distribution.partition_point(|s| *s < (high - 1 - o)); let i = distribution.partition_point(|s| *s < (high - 1 - o));
@@ -141,7 +144,6 @@ pub struct Decoys {
} }
impl Decoys { impl Decoys {
#[must_use]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.offsets.len() self.offsets.len()
} }
@@ -181,6 +183,7 @@ impl Decoys {
let per_second = { let per_second = {
let blocks = distribution.len().min(BLOCKS_PER_YEAR); let blocks = distribution.len().min(BLOCKS_PER_YEAR);
let outputs = high - distribution[distribution.len().saturating_sub(blocks + 1)]; let outputs = high - distribution[distribution.len().saturating_sub(blocks + 1)];
#[allow(clippy::as_conversions)]
(outputs as f64) / ((blocks * BLOCK_TIME) as f64) (outputs as f64) / ((blocks * BLOCK_TIME) as f64)
}; };

View File

@@ -124,7 +124,6 @@ impl ExtraField {
#[derive(Clone, PartialEq, Eq, Debug, Zeroize)] #[derive(Clone, PartialEq, Eq, Debug, Zeroize)]
pub struct Extra(Vec<ExtraField>); pub struct Extra(Vec<ExtraField>);
impl Extra { impl Extra {
#[must_use]
pub fn keys(&self) -> Option<(EdwardsPoint, Option<Vec<EdwardsPoint>>)> { pub fn keys(&self) -> Option<(EdwardsPoint, Option<Vec<EdwardsPoint>>)> {
let mut key = None; let mut key = None;
let mut additional = None; let mut additional = None;
@@ -141,7 +140,6 @@ impl Extra {
key.map(|key| (key, additional)) key.map(|key| (key, additional))
} }
#[must_use]
pub fn payment_id(&self) -> Option<PaymentId> { pub fn payment_id(&self) -> Option<PaymentId> {
for field in &self.0 { for field in &self.0 {
if let ExtraField::Nonce(data) = field { if let ExtraField::Nonce(data) = field {
@@ -151,7 +149,6 @@ impl Extra {
None None
} }
#[must_use]
pub fn data(&self) -> Vec<Vec<u8>> { pub fn data(&self) -> Vec<Vec<u8>> {
let mut res = vec![]; let mut res = vec![];
for field in &self.0 { for field in &self.0 {
@@ -201,7 +198,6 @@ impl Extra {
Ok(()) Ok(())
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut buf = vec![]; let mut buf = vec![];
self.write(&mut buf).unwrap(); self.write(&mut buf).unwrap();

View File

@@ -141,17 +141,14 @@ pub struct ViewPair {
} }
impl ViewPair { impl ViewPair {
#[must_use]
pub const fn new(spend: EdwardsPoint, view: Zeroizing<Scalar>) -> Self { pub const fn new(spend: EdwardsPoint, view: Zeroizing<Scalar>) -> Self {
Self { spend, view } Self { spend, view }
} }
#[must_use]
pub const fn spend(&self) -> EdwardsPoint { pub const fn spend(&self) -> EdwardsPoint {
self.spend self.spend
} }
#[must_use]
pub fn view(&self) -> EdwardsPoint { pub fn view(&self) -> EdwardsPoint {
self.view.deref() * &ED25519_BASEPOINT_TABLE self.view.deref() * &ED25519_BASEPOINT_TABLE
} }
@@ -176,7 +173,6 @@ impl ViewPair {
} }
/// Returns an address with the provided specification. /// Returns an address with the provided specification.
#[must_use]
pub fn address(&self, network: Network, spec: AddressSpec) -> MoneroAddress { pub fn address(&self, network: Network, spec: AddressSpec) -> MoneroAddress {
let mut spend = self.spend; let mut spend = self.spend;
let mut view: EdwardsPoint = self.view.deref() * &ED25519_BASEPOINT_TABLE; 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 /// 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). /// bug (specifically the Guaranteed feature from Featured Addresses).
#[must_use]
pub fn from_view(pair: ViewPair, burning_bug: Option<HashSet<CompressedEdwardsY>>) -> Self { pub fn from_view(pair: ViewPair, burning_bug: Option<HashSet<CompressedEdwardsY>>) -> Self {
let mut subaddresses = HashMap::new(); let mut subaddresses = HashMap::new();
subaddresses.insert(pair.spend.compress(), None); subaddresses.insert(pair.spend.compress(), None);

View File

@@ -32,7 +32,6 @@ impl AbsoluteId {
w.write_all(&[self.o]) w.write_all(&[self.o])
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = Vec::with_capacity(32 + 1); let mut serialized = Vec::with_capacity(32 + 1);
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();
@@ -61,7 +60,6 @@ impl OutputData {
w.write_all(&self.commitment.amount.to_le_bytes()) w.write_all(&self.commitment.amount.to_le_bytes())
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = Vec::with_capacity(32 + 32 + 32 + 8); let mut serialized = Vec::with_capacity(32 + 32 + 32 + 8);
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();
@@ -110,7 +108,6 @@ impl Metadata {
Ok(()) Ok(())
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = Vec::with_capacity(1 + 8 + 1); let mut serialized = Vec::with_capacity(1 + 8 + 1);
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();
@@ -151,22 +148,18 @@ pub struct ReceivedOutput {
} }
impl ReceivedOutput { impl ReceivedOutput {
#[must_use] pub fn key(&self) -> EdwardsPoint {
pub const fn key(&self) -> EdwardsPoint {
self.data.key self.data.key
} }
#[must_use] pub fn key_offset(&self) -> Scalar {
pub const fn key_offset(&self) -> Scalar {
self.data.key_offset self.data.key_offset
} }
#[must_use]
pub fn commitment(&self) -> Commitment { pub fn commitment(&self) -> Commitment {
self.data.commitment.clone() self.data.commitment.clone()
} }
#[must_use]
pub fn arbitrary_data(&self) -> &[Vec<u8>] { pub fn arbitrary_data(&self) -> &[Vec<u8>] {
&self.metadata.arbitrary_data &self.metadata.arbitrary_data
} }
@@ -177,7 +170,6 @@ impl ReceivedOutput {
self.metadata.write(w) self.metadata.write(w)
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut serialized = vec![]; let mut serialized = vec![];
self.write(&mut serialized).unwrap(); self.write(&mut serialized).unwrap();
@@ -223,22 +215,18 @@ impl SpendableOutput {
Ok(output) Ok(output)
} }
#[must_use] pub fn key(&self) -> EdwardsPoint {
pub const fn key(&self) -> EdwardsPoint {
self.output.key() self.output.key()
} }
#[must_use] pub fn key_offset(&self) -> Scalar {
pub const fn key_offset(&self) -> Scalar {
self.output.key_offset() self.output.key_offset()
} }
#[must_use]
pub fn commitment(&self) -> Commitment { pub fn commitment(&self) -> Commitment {
self.output.commitment() self.output.commitment()
} }
#[must_use]
pub fn arbitrary_data(&self) -> &[Vec<u8>] { pub fn arbitrary_data(&self) -> &[Vec<u8>] {
self.output.arbitrary_data() 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> ZeroizeOnDrop for Timelocked<O> {}
impl<O: Clone + Zeroize> Timelocked<O> { impl<O: Clone + Zeroize> Timelocked<O> {
#[must_use] pub fn timelock(&self) -> Timelock {
pub const fn timelock(&self) -> Timelock {
self.0 self.0
} }

View File

@@ -7,25 +7,21 @@ use rand_core::{RngCore, CryptoRng};
pub(crate) mod classic; pub(crate) mod classic;
use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed}; use classic::{CLASSIC_SEED_LENGTH, CLASSIC_SEED_LENGTH_WITH_CHECKSUM, ClassicSeed};
#[allow(clippy::std_instead_of_core)] /// Error when decoding a seed.
mod seed_error { #[derive(Clone, Copy, PartialEq, Eq, Debug)]
/// Error when decoding a seed. #[cfg_attr(feature = "std", derive(thiserror::Error))]
#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum SeedError {
#[cfg_attr(feature = "std", derive(thiserror::Error))] #[cfg_attr(feature = "std", error("invalid number of words in seed"))]
pub enum SeedError { InvalidSeedLength,
#[cfg_attr(feature = "std", error("invalid number of words in seed"))] #[cfg_attr(feature = "std", error("unknown language"))]
InvalidSeedLength, UnknownLanguage,
#[cfg_attr(feature = "std", error("unknown language"))] #[cfg_attr(feature = "std", error("invalid checksum"))]
UnknownLanguage, InvalidChecksum,
#[cfg_attr(feature = "std", error("invalid checksum"))] #[cfg_attr(feature = "std", error("english old seeds don't support checksums"))]
InvalidChecksum, EnglishOldWithChecksum,
#[cfg_attr(feature = "std", error("english old seeds don't support checksums"))] #[cfg_attr(feature = "std", error("invalid seed"))]
EnglishOldWithChecksum, InvalidSeed,
#[cfg_attr(feature = "std", error("invalid seed"))]
InvalidSeed,
}
} }
pub use seed_error::SeedError;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum Language { pub enum Language {
@@ -61,7 +57,6 @@ impl fmt::Debug for Seed {
impl Seed { impl Seed {
/// Create a new seed. /// Create a new seed.
#[must_use]
pub fn new<R: RngCore + CryptoRng>(rng: &mut R, lang: Language) -> Self { pub fn new<R: RngCore + CryptoRng>(rng: &mut R, lang: Language) -> Self {
Self::Classic(ClassicSeed::new(rng, lang)) Self::Classic(ClassicSeed::new(rng, lang))
} }
@@ -77,7 +72,6 @@ impl Seed {
} }
/// Create a Seed from entropy. /// Create a Seed from entropy.
#[must_use]
pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<Self> { pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<Self> {
ClassicSeed::from_entropy(lang, entropy).map(Self::Classic) ClassicSeed::from_entropy(lang, entropy).map(Self::Classic)
} }
@@ -90,7 +84,6 @@ impl Seed {
} }
/// Return the entropy for this seed. /// Return the entropy for this seed.
#[must_use]
pub fn entropy(&self) -> Zeroizing<[u8; 32]> { pub fn entropy(&self) -> Zeroizing<[u8; 32]> {
match self { match self {
Self::Classic(seed) => seed.entropy(), Self::Classic(seed) => seed.entropy(),

View File

@@ -25,7 +25,7 @@ struct SignableTransactionBuilderInternal {
impl SignableTransactionBuilderInternal { impl SignableTransactionBuilderInternal {
// Takes in the change address so users don't miss that they have to manually set one // 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 // 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 { Self {
protocol, protocol,
fee, fee,
@@ -91,7 +91,6 @@ impl SignableTransactionBuilder {
Self(self.0.clone()) Self(self.0.clone())
} }
#[must_use]
pub fn new(protocol: Protocol, fee: Fee, change_address: Option<Change>) -> Self { pub fn new(protocol: Protocol, fee: Fee, change_address: Option<Change>) -> Self {
Self(Arc::new(RwLock::new(SignableTransactionBuilderInternal::new( Self(Arc::new(RwLock::new(SignableTransactionBuilderInternal::new(
protocol, protocol,

View File

@@ -211,7 +211,6 @@ pub struct Fee {
} }
impl Fee { impl Fee {
#[must_use]
pub fn calculate(&self, weight: usize) -> u64 { pub fn calculate(&self, weight: usize) -> u64 {
((((self.per_weight * u64::try_from(weight).unwrap()) - 1) / self.mask) + 1) * self.mask ((((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 { impl Change {
/// Create a change output specification from a ViewPair, as needed to maintain privacy. /// Create a change output specification from a ViewPair, as needed to maintain privacy.
#[must_use]
pub fn new(view: &ViewPair, guaranteed: bool) -> Self { pub fn new(view: &ViewPair, guaranteed: bool) -> Self {
Self { Self {
address: view.address( address: view.address(
@@ -280,7 +278,6 @@ impl Change {
/// Create a fingerprintable change output specification which will harm privacy. /// Create a fingerprintable change output specification which will harm privacy.
/// ///
/// Only use this if you know what you're doing. /// Only use this if you know what you're doing.
#[must_use]
pub const fn fingerprintable(address: MoneroAddress) -> Self { pub const fn fingerprintable(address: MoneroAddress) -> Self {
Self { address, view: None } Self { address, view: None }
} }
@@ -394,8 +391,7 @@ impl SignableTransaction {
Ok(Self { protocol, r_seed, inputs, payments, data, fee }) Ok(Self { protocol, r_seed, inputs, payments, data, fee })
} }
#[must_use] pub fn fee(&self) -> u64 {
pub const fn fee(&self) -> u64 {
self.fee self.fee
} }
@@ -568,7 +564,6 @@ impl SignableTransaction {
/// The eventuality is defined as the TX extra/outputs this transaction will create, if signed /// 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 /// with the specified seed. This eventuality can be compared to on-chain transactions to see
/// if the transaction has already been signed and published. /// if the transaction has already been signed and published.
#[must_use]
pub fn eventuality(&self) -> Option<Eventuality> { pub fn eventuality(&self) -> Option<Eventuality> {
let inputs = self.inputs.iter().map(SpendableOutput::key).collect::<Vec<_>>(); let inputs = self.inputs.iter().map(SpendableOutput::key).collect::<Vec<_>>();
let (tx_key, additional, outputs, id) = Self::prepare_payments( 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 /// 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. /// transaction which doesn't satisfy this Eventuality will contain it.
#[must_use]
pub fn extra(&self) -> &[u8] { pub fn extra(&self) -> &[u8] {
&self.extra &self.extra
} }
@@ -817,7 +811,6 @@ impl Eventuality {
write_vec(write_byte, &self.extra, w) write_vec(write_byte, &self.extra, w)
} }
#[must_use]
pub fn serialize(&self) -> Vec<u8> { pub fn serialize(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(128); let mut buf = Vec::with_capacity(128);
self.write(&mut buf).unwrap(); self.write(&mut buf).unwrap();

View File

@@ -82,7 +82,6 @@ impl Default for MemDb {
impl MemDb { impl MemDb {
/// Create a new in-memory database. /// Create a new in-memory database.
#[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self::default() Self::default()
} }

View File

@@ -24,17 +24,14 @@ mod shims {
} }
impl Error { impl Error {
#[must_use]
pub fn new<E: 'static + Send + Sync>(kind: ErrorKind, error: E) -> Self { pub fn new<E: 'static + Send + Sync>(kind: ErrorKind, error: E) -> Self {
Self { kind, error: Box::new(error) } Self { kind, error: Box::new(error) }
} }
#[must_use]
pub const fn kind(&self) -> ErrorKind { pub const fn kind(&self) -> ErrorKind {
self.kind self.kind
} }
#[must_use]
pub fn into_inner(self) -> Option<Box<dyn Send + Sync>> { pub fn into_inner(self) -> Option<Box<dyn Send + Sync>> {
Some(self.error) Some(self.error)
} }

View File

@@ -1,6 +1,8 @@
use core::{ops::Deref, fmt}; use core::{ops::Deref, fmt};
use std::{io, collections::HashMap}; use std::{io, collections::HashMap};
use thiserror::Error;
use zeroize::{Zeroize, Zeroizing}; use zeroize::{Zeroize, Zeroizing};
use rand_core::{RngCore, CryptoRng}; use rand_core::{RngCore, CryptoRng};
@@ -68,7 +70,7 @@ impl<C: Ciphersuite, M: Message> EncryptionKeyMessage<C, M> {
} }
#[cfg(any(test, feature = "tests"))] #[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 self.enc_key
} }
} }
@@ -328,19 +330,13 @@ fn encryption_key_transcript(context: &str) -> RecommendedTranscript {
transcript transcript
} }
#[allow(clippy::std_instead_of_core)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
mod decryption_error { pub(crate) enum DecryptionError {
use thiserror::Error; #[error("accused provided an invalid signature")]
InvalidSignature,
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)] #[error("accuser provided an invalid decryption key")]
pub(crate) enum DecryptionError { InvalidProof,
#[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. // A simple box for managing encryption.
#[derive(Clone)] #[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 } EncryptionKeyMessage { msg, enc_key: self.enc_pub_key }
} }

View File

@@ -94,7 +94,7 @@ impl<C: Ciphersuite> KeyGenMachine<C> {
/// Create a new machine to generate a key. /// Create a new machine to generate a key.
/// ///
/// The context string should be unique among multisigs. /// 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 } Self { params, context, curve: PhantomData }
} }

View File

@@ -3,7 +3,8 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
use core::fmt::{self, Debug}; use core::fmt::{self, Debug};
extern crate alloc;
use thiserror::Error;
use zeroize::Zeroize; use zeroize::Zeroize;
@@ -61,58 +62,49 @@ impl fmt::Display for Participant {
} }
/// Various errors possible during key generation. /// Various errors possible during key generation.
#[allow(clippy::std_instead_of_core)] #[derive(Clone, PartialEq, Eq, Debug)]
mod dkg_error { #[cfg_attr(feature = "std", derive(Error))]
use core::fmt::Debug; pub enum DkgError<B: Clone + PartialEq + Eq + Debug> {
use thiserror::Error; /// A parameter was zero.
use super::Participant; #[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)] /// Invalid signing set.
#[cfg_attr(feature = "std", derive(Error))] #[cfg_attr(feature = "std", error("invalid signing set"))]
pub enum DkgError<B: Clone + PartialEq + Eq + Debug> { InvalidSigningSet,
/// A parameter was zero. /// Invalid amount of participants.
#[cfg_attr(feature = "std", error("a parameter was 0 (threshold {0}, participants {1})"))] #[cfg_attr(feature = "std", error("invalid participant quantity (expected {0}, got {1})"))]
ZeroParameter(u16, u16), InvalidParticipantQuantity(usize, usize),
/// The threshold exceeded the amount of participants. /// A participant was duplicated.
#[cfg_attr(feature = "std", error("invalid threshold (max {1}, got {0})"))] #[cfg_attr(feature = "std", error("duplicated participant ({0})"))]
InvalidThreshold(u16, u16), DuplicatedParticipant(Participant),
/// Invalid participant identifier. /// A participant was missing.
#[cfg_attr( #[cfg_attr(feature = "std", error("missing participant {0}"))]
feature = "std", MissingParticipant(Participant),
error("invalid participant (0 < participant <= {0}, yet participant is {1})")
)]
InvalidParticipant(u16, Participant),
/// Invalid signing set. /// An invalid proof of knowledge was provided.
#[cfg_attr(feature = "std", error("invalid signing set"))] #[cfg_attr(feature = "std", error("invalid proof of knowledge (participant {0})"))]
InvalidSigningSet, InvalidProofOfKnowledge(Participant),
/// Invalid amount of participants. /// An invalid DKG share was provided.
#[cfg_attr(feature = "std", error("invalid participant quantity (expected {0}, got {1})"))] #[cfg_attr(feature = "std", error("invalid share (participant {participant}, blame {blame})"))]
InvalidParticipantQuantity(usize, usize), InvalidShare { participant: Participant, blame: Option<B> },
/// 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> },
}
} }
pub use dkg_error::DkgError;
#[cfg(feature = "std")] #[cfg(feature = "std")]
mod lib { mod lib {
pub use super::*; pub use super::*;
use core::ops::Deref; use core::ops::Deref;
use alloc::sync::Arc; use std::{sync::Arc, io, collections::HashMap};
use std::{io, collections::HashMap};
use zeroize::Zeroizing; use zeroize::Zeroizing;
@@ -268,17 +260,17 @@ mod lib {
} }
/// Parameters for these keys. /// Parameters for these keys.
pub const fn params(&self) -> ThresholdParams { pub fn params(&self) -> ThresholdParams {
self.params self.params
} }
/// Secret share for these keys. /// 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 &self.secret_share
} }
/// Group key for these keys. /// Group key for these keys.
pub const fn group_key(&self) -> C::G { pub fn group_key(&self) -> C::G {
self.group_key self.group_key
} }
@@ -432,7 +424,7 @@ mod lib {
} }
/// Return the current offset in-use for these keys. /// 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 self.offset
} }
@@ -506,12 +498,12 @@ mod lib {
impl<C: Ciphersuite> ThresholdView<C> { impl<C: Ciphersuite> ThresholdView<C> {
/// Return the offset for this view. /// Return the offset for this view.
pub const fn offset(&self) -> C::F { pub fn offset(&self) -> C::F {
self.offset self.offset
} }
/// Return the group key. /// Return the group key.
pub const fn group_key(&self) -> C::G { pub fn group_key(&self) -> C::G {
self.group_key self.group_key
} }
@@ -521,7 +513,7 @@ mod lib {
} }
/// Return the interpolated, offset secret share. /// 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 &self.secret_share
} }

View File

@@ -1,6 +1,6 @@
use core::{marker::PhantomData, ops::Deref}; use core::{marker::PhantomData, ops::Deref};
use alloc::sync::Arc;
use std::{ use std::{
sync::Arc,
io::{self, Read, Write}, io::{self, Read, Write},
collections::HashMap, collections::HashMap,
}; };

View File

@@ -41,7 +41,7 @@ impl<G0: PrimeGroup, G1: PrimeGroup> Re<G0, G1> {
Self::R(G0::identity(), G1::identity()) Self::R(G0::identity(), G1::identity())
} }
pub(crate) const fn e_default() -> Self { pub(crate) fn e_default() -> Self {
Self::e(G0::Scalar::ZERO) Self::e(G0::Scalar::ZERO)
} }
} }

View File

@@ -26,7 +26,7 @@ pub(crate) enum BitSignature {
} }
impl BitSignature { impl BitSignature {
pub(crate) const fn to_u8(&self) -> u8 { pub(crate) fn to_u8(&self) -> u8 {
match self { match self {
Self::ClassicLinear => 0, Self::ClassicLinear => 0,
Self::ConciseLinear => 1, 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 { match algorithm {
0 => Self::ClassicLinear, 0 => Self::ClassicLinear,
1 => Self::ConciseLinear, 1 => Self::ConciseLinear,
@@ -45,14 +45,14 @@ impl BitSignature {
} }
} }
pub(crate) const fn bits(&self) -> usize { pub(crate) fn bits(&self) -> usize {
match self { match self {
Self::ClassicLinear | Self::EfficientLinear => 1, Self::ClassicLinear | Self::EfficientLinear => 1,
Self::ConciseLinear | Self::CompromiseLinear => 2, 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 #[allow(clippy::as_conversions, clippy::cast_possible_truncation)] // Needed for const
2_usize.pow(self.bits() as u32) 2_usize.pow(self.bits() as u32)
} }

View File

@@ -2,9 +2,10 @@ use core::ops::{Deref, DerefMut};
#[cfg(feature = "serialize")] #[cfg(feature = "serialize")]
use std::io::{self, Read, Write}; use std::io::{self, Read, Write};
use rand_core::{RngCore, CryptoRng}; use thiserror::Error;
use zeroize::{Zeroize, Zeroizing}; use zeroize::{Zeroize, Zeroizing};
use rand_core::{RngCore, CryptoRng};
use digest::{Digest, HashMarker}; use digest::{Digest, HashMarker};
@@ -92,27 +93,21 @@ impl<G: PrimeGroup> Generators<G> {
} }
/// Error for cross-group DLEq proofs. /// Error for cross-group DLEq proofs.
#[allow(clippy::std_instead_of_core)] #[derive(Error, PartialEq, Eq, Debug)]
mod dleq_error { pub enum DLEqError {
use thiserror::Error; /// Invalid proof of knowledge.
#[error("invalid proof of knowledge")]
#[derive(Error, PartialEq, Eq, Debug)] InvalidProofOfKnowledge,
pub enum DLEqError { /// Invalid proof length.
/// Invalid proof of knowledge. #[error("invalid proof length")]
#[error("invalid proof of knowledge")] InvalidProofLength,
InvalidProofOfKnowledge, /// Invalid challenge.
/// Invalid proof length. #[error("invalid challenge")]
#[error("invalid proof length")] InvalidChallenge,
InvalidProofLength, /// Invalid proof.
/// Invalid challenge. #[error("invalid proof")]
#[error("invalid challenge")] InvalidProof,
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 // This should never be directly instantiated and uses a u8 to represent internal values
// Any external usage is likely invalid // Any external usage is likely invalid

View File

@@ -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> { impl<C: Curve, T: Sync + Clone + Debug + Transcript, H: Hram<C>> Schnorr<C, T, H> {
/// Construct a Schnorr algorithm continuing the specified transcript. /// 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 } 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. /// Construct a IETF-compatible Schnorr algorithm.
/// ///
/// Please see the `IetfSchnorr` documentation for the full details of this. /// Please see the `IetfSchnorr` documentation for the full details of this.
pub const fn ietf() -> Self { pub fn ietf() -> Self {
Self::new(IetfTranscript(vec![])) Self::new(IetfTranscript(vec![]))
} }
} }

View File

@@ -1,8 +1,11 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))] #![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
use core::fmt::Debug;
use std::collections::HashMap; use std::collections::HashMap;
use thiserror::Error;
/// Distributed key generation protocol. /// Distributed key generation protocol.
pub use dkg::{self, Participant, ThresholdParams, ThresholdCore, ThresholdKeys, ThresholdView}; pub use dkg::{self, Participant, ThresholdParams, ThresholdCore, ThresholdKeys, ThresholdView};
@@ -20,32 +23,25 @@ pub mod sign;
#[cfg(any(test, feature = "tests"))] #[cfg(any(test, feature = "tests"))]
pub mod tests; pub mod tests;
#[allow(clippy::std_instead_of_core)] /// Various errors possible during signing.
mod frost_error { #[derive(Clone, Copy, PartialEq, Eq, Debug, Error)]
use core::fmt::Debug; pub enum FrostError {
use thiserror::Error; #[error("invalid participant (0 < participant <= {0}, yet participant is {1})")]
use dkg::Participant; InvalidParticipant(u16, Participant),
/// Various errors possible during signing. #[error("invalid signing set ({0})")]
#[derive(Clone, Copy, PartialEq, Eq, Debug, Error)] InvalidSigningSet(&'static str),
pub enum FrostError { #[error("invalid participant quantity (expected {0}, got {1})")]
#[error("invalid participant (0 < participant <= {0}, yet participant is {1})")] InvalidParticipantQuantity(usize, usize),
InvalidParticipant(u16, Participant), #[error("duplicated participant ({0})")]
#[error("invalid signing set ({0})")] DuplicatedParticipant(Participant),
InvalidSigningSet(&'static str), #[error("missing participant {0}")]
#[error("invalid participant quantity (expected {0}, got {1})")] MissingParticipant(Participant),
InvalidParticipantQuantity(usize, usize),
#[error("duplicated participant ({0})")]
DuplicatedParticipant(Participant),
#[error("missing participant {0}")]
MissingParticipant(Participant),
#[error("invalid preprocess (participant {0})")] #[error("invalid preprocess (participant {0})")]
InvalidPreprocess(Participant), InvalidPreprocess(Participant),
#[error("invalid share (participant {0})")] #[error("invalid share (participant {0})")]
InvalidShare(Participant), InvalidShare(Participant),
}
} }
pub use frost_error::FrostError;
/// Validate a map of values to have the expected participants. /// Validate a map of values to have the expected participants.
pub fn validate_map<T>( pub fn validate_map<T>(

View File

@@ -53,7 +53,7 @@ struct Params<C: Curve, A: Algorithm<C>> {
} }
impl<C: Curve, A: Algorithm<C>> Params<C, A> { 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 } Self { algorithm, keys }
} }
@@ -111,7 +111,7 @@ pub struct AlgorithmMachine<C: Curve, A: Algorithm<C>> {
impl<C: Curve, A: Algorithm<C>> AlgorithmMachine<C, A> { impl<C: Curve, A: Algorithm<C>> AlgorithmMachine<C, A> {
/// Creates a new machine to generate a signature with the specified keys. /// 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) } Self { params: Params::new(algorithm, keys) }
} }

View File

@@ -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 7 is more efficient at 475 with 500µs per
Pippenger 8 is more efficient at 875 with 499µ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))] #[cfg(not(debug_assertions))]
if len == 0 { if len == 0 {
Algorithm::Null Algorithm::Null

View File

@@ -61,7 +61,7 @@ enum DigestTranscriptMember {
} }
impl DigestTranscriptMember { impl DigestTranscriptMember {
const fn as_u8(&self) -> u8 { fn as_u8(&self) -> u8 {
match self { match self {
Self::Name => 0, Self::Name => 0,
Self::Domain => 1, Self::Domain => 1,