mirror of
https://github.com/serai-dex/serai.git
synced 2024-12-22 11:39:35 +00:00
Further expand clippy workspace lints
Achieves a notable amount of reduced async and clones.
This commit is contained in:
parent
ea3af28139
commit
065d314e2a
113 changed files with 596 additions and 724 deletions
26
Cargo.toml
26
Cargo.toml
|
@ -121,3 +121,29 @@ inefficient_to_string = "deny"
|
|||
invalid_upcast_comparisons = "deny"
|
||||
large_stack_arrays = "deny"
|
||||
linkedlist = "deny"
|
||||
macro_use_imports = "deny"
|
||||
manual_instant_elapsed = "deny"
|
||||
manual_let_else = "deny"
|
||||
manual_ok_or = "deny"
|
||||
manual_string_new = "deny"
|
||||
map_unwrap_or = "deny"
|
||||
match_bool = "deny"
|
||||
match_same_arms = "deny"
|
||||
missing_fields_in_debug = "deny"
|
||||
needless_continue = "deny"
|
||||
needless_pass_by_value = "deny"
|
||||
ptr_cast_constness = "deny"
|
||||
range_minus_one = "deny"
|
||||
range_plus_one = "deny"
|
||||
redundant_closure_for_method_calls = "deny"
|
||||
redundant_else = "deny"
|
||||
string_add_assign = "deny"
|
||||
unchecked_duration_subtraction = "deny"
|
||||
uninlined_format_args = "deny"
|
||||
unnecessary_box_returns = "deny"
|
||||
unnecessary_join = "deny"
|
||||
unnecessary_wraps = "deny"
|
||||
unnested_or_patterns = "deny"
|
||||
unused_async = "deny"
|
||||
unused_self = "deny"
|
||||
zero_sized_map_values = "deny"
|
||||
|
|
|
@ -29,9 +29,9 @@ fn test_algorithm() {
|
|||
Schnorr::<RecommendedTranscript>::new(RecommendedTranscript::new(b"bitcoin-serai sign test"));
|
||||
let sig = sign(
|
||||
&mut OsRng,
|
||||
algo.clone(),
|
||||
&algo,
|
||||
keys.clone(),
|
||||
algorithm_machines(&mut OsRng, algo, &keys),
|
||||
algorithm_machines(&mut OsRng, &algo, &keys),
|
||||
Hash::hash(MESSAGE).as_ref(),
|
||||
);
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ impl SignableTransaction {
|
|||
pub fn new(
|
||||
mut inputs: Vec<ReceivedOutput>,
|
||||
payments: &[(Address, u64)],
|
||||
change: Option<Address>,
|
||||
change: Option<&Address>,
|
||||
data: Option<Vec<u8>>,
|
||||
fee_per_weight: u64,
|
||||
) -> Result<SignableTransaction, TransactionError> {
|
||||
|
@ -140,7 +140,7 @@ impl SignableTransaction {
|
|||
}
|
||||
}
|
||||
|
||||
if data.as_ref().map(|data| data.len()).unwrap_or(0) > 80 {
|
||||
if data.as_ref().map_or(0, Vec::len) > 80 {
|
||||
Err(TransactionError::TooMuchData)?;
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ impl SignableTransaction {
|
|||
}
|
||||
|
||||
// If there's a change address, check if there's change to give it
|
||||
if let Some(change) = change.as_ref() {
|
||||
if let Some(change) = change {
|
||||
let weight_with_change = Self::calculate_weight(tx_ins.len(), payments, Some(change));
|
||||
let fee_with_change = fee_per_weight * weight_with_change;
|
||||
if let Some(value) = input_sat.checked_sub(payment_sat + fee_with_change) {
|
||||
|
@ -263,7 +263,7 @@ impl SignableTransaction {
|
|||
/// Returns None if the wrong keys are used.
|
||||
pub fn multisig(
|
||||
self,
|
||||
keys: ThresholdKeys<Secp256k1>,
|
||||
keys: &ThresholdKeys<Secp256k1>,
|
||||
mut transcript: RecommendedTranscript,
|
||||
) -> Option<TransactionMachine> {
|
||||
transcript.domain_separate(b"bitcoin_transaction");
|
||||
|
|
|
@ -91,14 +91,14 @@ fn keys() -> (HashMap<Participant, ThresholdKeys<Secp256k1>>, ProjectivePoint) {
|
|||
|
||||
fn sign(
|
||||
keys: &HashMap<Participant, ThresholdKeys<Secp256k1>>,
|
||||
tx: SignableTransaction,
|
||||
tx: &SignableTransaction,
|
||||
) -> Transaction {
|
||||
let mut machines = HashMap::new();
|
||||
for i in (1 ..= THRESHOLD).map(|i| Participant::new(i).unwrap()) {
|
||||
machines.insert(
|
||||
i,
|
||||
tx.clone()
|
||||
.multisig(keys[&i].clone(), RecommendedTranscript::new(b"bitcoin-serai Test Transaction"))
|
||||
.multisig(&keys[&i].clone(), RecommendedTranscript::new(b"bitcoin-serai Test Transaction"))
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ async_sequential! {
|
|||
// No change
|
||||
assert!(SignableTransaction::new(inputs.clone(), &[(addr(), 1000)], None, None, FEE).is_ok());
|
||||
// Consolidation TX
|
||||
assert!(SignableTransaction::new(inputs.clone(), &[], Some(addr()), None, FEE).is_ok());
|
||||
assert!(SignableTransaction::new(inputs.clone(), &[], Some(&addr()), None, FEE).is_ok());
|
||||
// Data
|
||||
assert!(SignableTransaction::new(inputs.clone(), &[], None, Some(vec![]), FEE).is_ok());
|
||||
// No outputs
|
||||
|
@ -229,7 +229,7 @@ async_sequential! {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
SignableTransaction::new(inputs.clone(), &[], Some(addr()), None, 0),
|
||||
SignableTransaction::new(inputs.clone(), &[], Some(&addr()), None, 0),
|
||||
Err(TransactionError::TooLowFee),
|
||||
);
|
||||
|
||||
|
@ -274,13 +274,13 @@ async_sequential! {
|
|||
let tx = SignableTransaction::new(
|
||||
vec![output.clone(), offset_output.clone()],
|
||||
&payments,
|
||||
Some(change_addr.clone()),
|
||||
Some(&change_addr),
|
||||
None,
|
||||
FEE
|
||||
).unwrap();
|
||||
let needed_fee = tx.needed_fee();
|
||||
let expected_id = tx.txid();
|
||||
let tx = sign(&keys, tx);
|
||||
let tx = sign(&keys, &tx);
|
||||
|
||||
assert_eq!(tx.output.len(), 3);
|
||||
|
||||
|
@ -341,10 +341,10 @@ async_sequential! {
|
|||
|
||||
let tx = sign(
|
||||
&keys,
|
||||
SignableTransaction::new(
|
||||
&SignableTransaction::new(
|
||||
vec![output],
|
||||
&[],
|
||||
Some(Address::<NetworkChecked>::new(Network::Regtest, address_payload(key).unwrap())),
|
||||
Some(&Address::<NetworkChecked>::new(Network::Regtest, address_payload(key).unwrap())),
|
||||
Some(data.clone()),
|
||||
FEE
|
||||
).unwrap()
|
||||
|
|
|
@ -112,9 +112,9 @@ async fn test_ecrecover_hack() {
|
|||
let algo = IetfSchnorr::<Secp256k1, crypto::EthereumHram>::ietf();
|
||||
let sig = sign(
|
||||
&mut OsRng,
|
||||
algo.clone(),
|
||||
&algo,
|
||||
keys.clone(),
|
||||
algorithm_machines(&mut OsRng, algo, &keys),
|
||||
algorithm_machines(&mut OsRng, &algo, &keys),
|
||||
full_message,
|
||||
);
|
||||
let mut processed_sig =
|
||||
|
|
|
@ -47,13 +47,8 @@ fn test_signing() {
|
|||
const MESSAGE: &[u8] = b"Hello, World!";
|
||||
|
||||
let algo = IetfSchnorr::<Secp256k1, EthereumHram>::ietf();
|
||||
let _sig = sign(
|
||||
&mut OsRng,
|
||||
algo,
|
||||
keys.clone(),
|
||||
algorithm_machines(&mut OsRng, IetfSchnorr::<Secp256k1, EthereumHram>::ietf(), &keys),
|
||||
MESSAGE,
|
||||
);
|
||||
let _sig =
|
||||
sign(&mut OsRng, &algo, keys.clone(), algorithm_machines(&mut OsRng, &algo, &keys), MESSAGE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -79,9 +74,9 @@ fn test_ecrecover_hack() {
|
|||
let algo = IetfSchnorr::<Secp256k1, EthereumHram>::ietf();
|
||||
let sig = sign(
|
||||
&mut OsRng,
|
||||
algo.clone(),
|
||||
&algo,
|
||||
keys.clone(),
|
||||
algorithm_machines(&mut OsRng, algo, &keys),
|
||||
algorithm_machines(&mut OsRng, &algo, &keys),
|
||||
full_message,
|
||||
);
|
||||
|
||||
|
|
|
@ -28,10 +28,10 @@ fn serialize(generators_string: &mut String, points: &[EdwardsPoint]) {
|
|||
fn generators(prefix: &'static str, path: &str) {
|
||||
let generators = bulletproofs_generators(prefix.as_bytes());
|
||||
#[allow(non_snake_case)]
|
||||
let mut G_str = "".to_string();
|
||||
let mut G_str = String::new();
|
||||
serialize(&mut G_str, &generators.G);
|
||||
#[allow(non_snake_case)]
|
||||
let mut H_str = "".to_string();
|
||||
let mut H_str = String::new();
|
||||
serialize(&mut H_str, &generators.H);
|
||||
|
||||
let path = Path::new(&env::var("OUT_DIR").unwrap()).join(path);
|
||||
|
|
|
@ -239,7 +239,7 @@ mod binaries {
|
|||
assert!(batch.verify_vartime());
|
||||
}
|
||||
|
||||
println!("Deserialized, hashed, and reserialized {block_i} with {} TXs", txs_len);
|
||||
println!("Deserialized, hashed, and reserialized {block_i} with {txs_len} TXs");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use std_shims::{
|
|||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use zeroize::Zeroize;
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
|
||||
use curve25519_dalek::edwards::EdwardsPoint;
|
||||
use multiexp::BatchVerifier;
|
||||
|
@ -91,7 +91,7 @@ impl Bulletproofs {
|
|||
Bulletproofs::Plus(
|
||||
AggregateRangeStatement::new(outputs.iter().map(|com| DfgPoint(com.calculate())).collect())
|
||||
.unwrap()
|
||||
.prove(rng, AggregateRangeWitness::new(outputs).unwrap())
|
||||
.prove(rng, &Zeroizing::new(AggregateRangeWitness::new(outputs).unwrap()))
|
||||
.unwrap(),
|
||||
)
|
||||
})
|
||||
|
|
|
@ -223,7 +223,7 @@ impl OriginalStruct {
|
|||
let A = normalize(&self.A);
|
||||
let S = normalize(&self.S);
|
||||
|
||||
let commitments = commitments.iter().map(|c| c.mul_by_cofactor()).collect::<Vec<_>>();
|
||||
let commitments = commitments.iter().map(EdwardsPoint::mul_by_cofactor).collect::<Vec<_>>();
|
||||
|
||||
// Verify it
|
||||
let mut proof = Vec::with_capacity(4 + commitments.len());
|
||||
|
|
|
@ -2,7 +2,7 @@ use std_shims::vec::Vec;
|
|||
|
||||
use rand_core::{RngCore, CryptoRng};
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop, Zeroizing};
|
||||
|
||||
use multiexp::{multiexp, multiexp_vartime, BatchVerifier};
|
||||
use group::{
|
||||
|
@ -142,7 +142,7 @@ impl AggregateRangeStatement {
|
|||
A_terms.push((y_mn_plus_one, commitment_accum));
|
||||
A_terms.push((
|
||||
((y_pows * z) - (d.sum() * y_mn_plus_one * z) - (y_pows * z.square())),
|
||||
generators.g(),
|
||||
Generators::g(),
|
||||
));
|
||||
|
||||
(y, d_descending_y, y_mn_plus_one, z, ScalarVector(z_pow), A + multiexp_vartime(&A_terms))
|
||||
|
@ -151,7 +151,7 @@ impl AggregateRangeStatement {
|
|||
pub(crate) fn prove<R: RngCore + CryptoRng>(
|
||||
self,
|
||||
rng: &mut R,
|
||||
witness: AggregateRangeWitness,
|
||||
witness: &AggregateRangeWitness,
|
||||
) -> Option<AggregateRangeProof> {
|
||||
// Check for consistency with the witness
|
||||
if self.V.len() != witness.values.len() {
|
||||
|
@ -202,7 +202,7 @@ impl AggregateRangeStatement {
|
|||
for (i, a_r) in a_r.0.iter().enumerate() {
|
||||
A_terms.push((*a_r, generators.generator(GeneratorsList::HBold1, i)));
|
||||
}
|
||||
A_terms.push((alpha, generators.h()));
|
||||
A_terms.push((alpha, Generators::h()));
|
||||
let mut A = multiexp(&A_terms);
|
||||
A_terms.zeroize();
|
||||
|
||||
|
@ -222,7 +222,7 @@ impl AggregateRangeStatement {
|
|||
Some(AggregateRangeProof {
|
||||
A,
|
||||
wip: WipStatement::new(generators, A_hat, y)
|
||||
.prove(rng, transcript, WipWitness::new(a_l, a_r, alpha).unwrap())
|
||||
.prove(rng, transcript, &Zeroizing::new(WipWitness::new(a_l, a_r, alpha).unwrap()))
|
||||
.unwrap(),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -31,8 +31,6 @@ pub(crate) enum GeneratorsList {
|
|||
// TODO: Table these
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct Generators {
|
||||
g: EdwardsPoint,
|
||||
|
||||
g_bold1: &'static [EdwardsPoint],
|
||||
h_bold1: &'static [EdwardsPoint],
|
||||
}
|
||||
|
@ -47,18 +45,18 @@ impl Generators {
|
|||
#[allow(clippy::new_without_default)]
|
||||
pub(crate) fn new() -> Self {
|
||||
let gens = generators::GENERATORS();
|
||||
Generators { g: dalek_ff_group::EdwardsPoint(crate::H()), g_bold1: &gens.G, h_bold1: &gens.H }
|
||||
Generators { g_bold1: &gens.G, h_bold1: &gens.H }
|
||||
}
|
||||
|
||||
pub(crate) fn len(&self) -> usize {
|
||||
self.g_bold1.len()
|
||||
}
|
||||
|
||||
pub(crate) fn g(&self) -> EdwardsPoint {
|
||||
self.g
|
||||
pub(crate) fn g() -> EdwardsPoint {
|
||||
dalek_ff_group::EdwardsPoint(crate::H())
|
||||
}
|
||||
|
||||
pub(crate) fn h(&self) -> EdwardsPoint {
|
||||
pub(crate) fn h() -> EdwardsPoint {
|
||||
EdwardsPoint::generator()
|
||||
}
|
||||
|
||||
|
@ -74,11 +72,7 @@ impl Generators {
|
|||
let generators = padded_pow_of_2(generators);
|
||||
assert!(generators <= self.g_bold1.len());
|
||||
|
||||
Generators {
|
||||
g: self.g,
|
||||
g_bold1: &self.g_bold1[.. generators],
|
||||
h_bold1: &self.h_bold1[.. generators],
|
||||
}
|
||||
Generators { g_bold1: &self.g_bold1[.. generators], h_bold1: &self.h_bold1[.. generators] }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ impl WipStatement {
|
|||
self,
|
||||
rng: &mut R,
|
||||
mut transcript: Scalar,
|
||||
witness: WipWitness,
|
||||
witness: &WipWitness,
|
||||
) -> Option<WipProof> {
|
||||
let WipStatement { generators, P, mut y } = self;
|
||||
#[cfg(not(debug_assertions))]
|
||||
|
@ -198,7 +198,7 @@ impl WipStatement {
|
|||
if generators.len() != witness.a.len() {
|
||||
return None;
|
||||
}
|
||||
let (g, h) = (generators.g(), generators.h());
|
||||
let (g, h) = (Generators::g(), Generators::h());
|
||||
let mut g_bold = vec![];
|
||||
let mut h_bold = vec![];
|
||||
for i in 0 .. generators.len() {
|
||||
|
@ -345,7 +345,7 @@ impl WipStatement {
|
|||
) -> bool {
|
||||
let WipStatement { generators, P, y } = self;
|
||||
|
||||
let (g, h) = (generators.g(), generators.h());
|
||||
let (g, h) = (Generators::g(), Generators::h());
|
||||
|
||||
// Verify the L/R lengths
|
||||
{
|
||||
|
|
|
@ -96,7 +96,7 @@ fn core(
|
|||
msg: &[u8; 32],
|
||||
D: &EdwardsPoint,
|
||||
s: &[Scalar],
|
||||
A_c1: Mode,
|
||||
A_c1: &Mode,
|
||||
) -> ((EdwardsPoint, Scalar, Scalar), Scalar) {
|
||||
let n = ring.len();
|
||||
|
||||
|
@ -164,7 +164,7 @@ fn core(
|
|||
Mode::Verify(c1) => {
|
||||
start = 0;
|
||||
end = n;
|
||||
c = c1;
|
||||
c = *c1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,7 +226,7 @@ impl Clsag {
|
|||
s.push(random_scalar(rng));
|
||||
}
|
||||
let ((D, p, c), c1) =
|
||||
core(&input.decoys.ring, I, &pseudo_out, msg, &D, &s, Mode::Sign(r, A, AH));
|
||||
core(&input.decoys.ring, I, &pseudo_out, msg, &D, &s, &Mode::Sign(r, A, AH));
|
||||
|
||||
(Clsag { D, s, c1 }, pseudo_out, p, c * z)
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ impl Clsag {
|
|||
Err(ClsagError::InvalidD)?;
|
||||
}
|
||||
|
||||
let (_, c1) = core(ring, I, pseudo_out, msg, &D, &self.s, Mode::Verify(self.c1));
|
||||
let (_, c1) = core(ring, I, pseudo_out, msg, &D, &self.s, &Mode::Verify(self.c1));
|
||||
if c1 != self.c1 {
|
||||
Err(ClsagError::InvalidC1)?;
|
||||
}
|
||||
|
|
|
@ -104,13 +104,11 @@ impl RctType {
|
|||
|
||||
pub fn compact_encrypted_amounts(&self) -> bool {
|
||||
match self {
|
||||
RctType::Null => false,
|
||||
RctType::MlsagAggregate => false,
|
||||
RctType::MlsagIndividual => false,
|
||||
RctType::Null |
|
||||
RctType::MlsagAggregate |
|
||||
RctType::MlsagIndividual |
|
||||
RctType::Bulletproofs => false,
|
||||
RctType::BulletproofsCompactAmount => true,
|
||||
RctType::Clsag => true,
|
||||
RctType::BulletproofsPlus => true,
|
||||
RctType::BulletproofsCompactAmount | RctType::Clsag | RctType::BulletproofsPlus => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -151,9 +149,7 @@ impl RctBase {
|
|||
RctType::from_byte(read_byte(r)?).ok_or_else(|| io::Error::other("invalid RCT type"))?;
|
||||
|
||||
match rct_type {
|
||||
RctType::Null => {}
|
||||
RctType::MlsagAggregate => {}
|
||||
RctType::MlsagIndividual => {}
|
||||
RctType::Null | RctType::MlsagAggregate | RctType::MlsagIndividual => {}
|
||||
RctType::Bulletproofs |
|
||||
RctType::BulletproofsCompactAmount |
|
||||
RctType::Clsag |
|
||||
|
@ -325,7 +321,7 @@ impl RctPrunable {
|
|||
RctPrunable::MlsagBorromean { borromean, .. } => {
|
||||
borromean.iter().try_for_each(|rs| rs.write(w))
|
||||
}
|
||||
RctPrunable::MlsagBulletproofs { bulletproofs, .. } => bulletproofs.signature_write(w),
|
||||
RctPrunable::MlsagBulletproofs { bulletproofs, .. } |
|
||||
RctPrunable::Clsag { bulletproofs, .. } => bulletproofs.signature_write(w),
|
||||
}
|
||||
}
|
||||
|
@ -386,8 +382,8 @@ impl RctSignatures {
|
|||
serialized
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(decoys: Vec<usize>, outputs: usize, r: &mut R) -> io::Result<RctSignatures> {
|
||||
pub fn read<R: Read>(decoys: &[usize], outputs: usize, r: &mut R) -> io::Result<RctSignatures> {
|
||||
let base = RctBase::read(decoys.len(), outputs, r)?;
|
||||
Ok(RctSignatures { base: base.0, prunable: RctPrunable::read(base.1, &decoys, outputs, r)? })
|
||||
Ok(RctSignatures { base: base.0, prunable: RctPrunable::read(base.1, decoys, outputs, r)? })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ impl HttpRpc {
|
|||
Err(RpcError::ConnectionError("invalid amount of passwords".to_string()))?;
|
||||
}
|
||||
|
||||
let client = Client::without_connection_pool(url.clone())
|
||||
let client = Client::without_connection_pool(&url)
|
||||
.map_err(|_| RpcError::ConnectionError("invalid URL".to_string()))?;
|
||||
// Obtain the initial challenge, which also somewhat validates this connection
|
||||
let challenge = Self::digest_auth_challenge(
|
||||
|
|
|
@ -23,7 +23,7 @@ fn test_aggregate_range_proof() {
|
|||
let statement = AggregateRangeStatement::new(commitment_points).unwrap();
|
||||
let witness = AggregateRangeWitness::new(&commitments).unwrap();
|
||||
|
||||
let proof = statement.clone().prove(&mut OsRng, witness).unwrap();
|
||||
let proof = statement.clone().prove(&mut OsRng, &witness).unwrap();
|
||||
statement.verify(&mut OsRng, &mut verifier, (), proof);
|
||||
}
|
||||
assert!(verifier.verify_vartime());
|
||||
|
|
|
@ -23,7 +23,7 @@ fn test_zero_weighted_inner_product() {
|
|||
let witness = WipWitness::new(ScalarVector::new(1), ScalarVector::new(1), Scalar::ZERO).unwrap();
|
||||
|
||||
let transcript = Scalar::random(&mut OsRng);
|
||||
let proof = statement.clone().prove(&mut OsRng, transcript, witness).unwrap();
|
||||
let proof = statement.clone().prove(&mut OsRng, transcript, &witness).unwrap();
|
||||
|
||||
let mut verifier = BatchVerifier::new(1);
|
||||
statement.verify(&mut OsRng, &mut verifier, (), transcript, proof);
|
||||
|
@ -37,8 +37,8 @@ fn test_weighted_inner_product() {
|
|||
let generators = Generators::new();
|
||||
for i in [1, 2, 4, 8, 16, 32] {
|
||||
let generators = generators.reduce(i);
|
||||
let g = generators.g();
|
||||
let h = generators.h();
|
||||
let g = Generators::g();
|
||||
let h = Generators::h();
|
||||
assert_eq!(generators.len(), i);
|
||||
let mut g_bold = vec![];
|
||||
let mut h_bold = vec![];
|
||||
|
@ -75,7 +75,7 @@ fn test_weighted_inner_product() {
|
|||
let witness = WipWitness::new(a, b, alpha).unwrap();
|
||||
|
||||
let transcript = Scalar::random(&mut OsRng);
|
||||
let proof = statement.clone().prove(&mut OsRng, transcript, witness).unwrap();
|
||||
let proof = statement.clone().prove(&mut OsRng, transcript, &witness).unwrap();
|
||||
statement.verify(&mut OsRng, &mut verifier, (), transcript, proof);
|
||||
}
|
||||
assert!(verifier.verify_vartime());
|
||||
|
|
|
@ -119,9 +119,9 @@ fn clsag_multisig() {
|
|||
|
||||
sign(
|
||||
&mut OsRng,
|
||||
algorithm.clone(),
|
||||
&algorithm,
|
||||
keys.clone(),
|
||||
algorithm_machines(&mut OsRng, algorithm, &keys),
|
||||
algorithm_machines(&mut OsRng, &algorithm, &keys),
|
||||
&[1; 32],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ fn test_polyseed() {
|
|||
let seed_without_accents = |seed: &str| {
|
||||
seed
|
||||
.split_whitespace()
|
||||
.map(|w| w.chars().filter(|c| c.is_ascii()).collect::<String>())
|
||||
.map(|w| w.chars().filter(char::is_ascii).collect::<String>())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ")
|
||||
};
|
||||
|
|
|
@ -331,14 +331,14 @@ impl Transaction {
|
|||
}
|
||||
} else if prefix.version == 2 {
|
||||
rct_signatures = RctSignatures::read(
|
||||
prefix
|
||||
&prefix
|
||||
.inputs
|
||||
.iter()
|
||||
.map(|input| match input {
|
||||
Input::Gen(_) => 0,
|
||||
Input::ToKey { key_offsets, .. } => key_offsets.len(),
|
||||
})
|
||||
.collect(),
|
||||
.collect::<Vec<_>>(),
|
||||
prefix.outputs.len(),
|
||||
r,
|
||||
)?;
|
||||
|
|
|
@ -356,17 +356,19 @@ impl Scanner {
|
|||
let output_key = output_key.unwrap();
|
||||
|
||||
for key in [Some(Some(&tx_key)), additional.as_ref().map(|additional| additional.get(o))] {
|
||||
let key = if let Some(Some(key)) = key {
|
||||
key
|
||||
} else if let Some(None) = key {
|
||||
// This is non-standard. There were additional keys, yet not one for this output
|
||||
// https://github.com/monero-project/monero/
|
||||
// blob/04a1e2875d6e35e27bb21497988a6c822d319c28/
|
||||
// src/cryptonote_basic/cryptonote_format_utils.cpp#L1062
|
||||
// TODO: Should this return? Where does Monero set the trap handler for this exception?
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
let key = match key {
|
||||
Some(Some(key)) => key,
|
||||
Some(None) => {
|
||||
// This is non-standard. There were additional keys, yet not one for this output
|
||||
// https://github.com/monero-project/monero/
|
||||
// blob/04a1e2875d6e35e27bb21497988a6c822d319c28/
|
||||
// src/cryptonote_basic/cryptonote_format_utils.cpp#L1062
|
||||
// TODO: Should this return? Where does Monero set the trap handler for this exception?
|
||||
continue;
|
||||
}
|
||||
None => {
|
||||
break;
|
||||
}
|
||||
};
|
||||
let (view_tag, shared_key, payment_id_xor) = shared_key(
|
||||
if self.burning_bug.is_none() { Some(uniqueness(&tx.prefix.inputs)) } else { None },
|
||||
|
|
|
@ -134,6 +134,7 @@ fn checksum_index(words: &[Zeroizing<String>], lang: &WordList) -> usize {
|
|||
}
|
||||
|
||||
// Convert a private key to a seed
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
fn key_to_seed(lang: Language, key: Zeroizing<Scalar>) -> ClassicSeed {
|
||||
let bytes = Zeroizing::new(key.to_bytes());
|
||||
|
||||
|
@ -282,6 +283,7 @@ impl ClassicSeed {
|
|||
key_to_seed(lang, Zeroizing::new(random_scalar(rng)))
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_string(words: Zeroizing<String>) -> Result<ClassicSeed, SeedError> {
|
||||
let (lang, entropy) = seed_to_bytes(&words)?;
|
||||
|
||||
|
@ -297,6 +299,7 @@ impl ClassicSeed {
|
|||
Ok(Self::from_entropy(lang, entropy).unwrap())
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_entropy(lang: Language, entropy: Zeroizing<[u8; 32]>) -> Option<ClassicSeed> {
|
||||
Option::from(Scalar::from_canonical_bytes(*entropy))
|
||||
.map(|scalar| key_to_seed(lang, Zeroizing::new(scalar)))
|
||||
|
|
|
@ -262,6 +262,7 @@ impl Polyseed {
|
|||
}
|
||||
|
||||
/// Create a new `Polyseed` from a String.
|
||||
#[allow(clippy::needless_pass_by_value)]
|
||||
pub fn from_string(seed: Zeroizing<String>) -> Result<Polyseed, SeedError> {
|
||||
// Decode the seed into its polynomial coefficients
|
||||
let mut poly = [0; POLYSEED_LENGTH];
|
||||
|
@ -302,7 +303,7 @@ impl Polyseed {
|
|||
}
|
||||
|
||||
let Some(coeff) = (if lang.has_accent {
|
||||
let ascii = |word: &str| word.chars().filter(|c| c.is_ascii()).collect::<String>();
|
||||
let ascii = |word: &str| word.chars().filter(char::is_ascii).collect::<String>();
|
||||
check_if_matches(
|
||||
lang.has_prefix,
|
||||
lang.words.iter().map(|lang_word| ascii(lang_word)),
|
||||
|
|
|
@ -136,7 +136,7 @@ impl SignableTransactionBuilder {
|
|||
read.r_seed.clone(),
|
||||
read.inputs.clone(),
|
||||
read.payments.clone(),
|
||||
read.change_address.clone(),
|
||||
&read.change_address,
|
||||
read.data.clone(),
|
||||
read.fee_rate,
|
||||
)
|
||||
|
|
|
@ -415,7 +415,7 @@ impl SignableTransaction {
|
|||
r_seed: Option<Zeroizing<[u8; 32]>>,
|
||||
inputs: Vec<(SpendableOutput, Decoys)>,
|
||||
payments: Vec<(MoneroAddress, u64)>,
|
||||
change: Change,
|
||||
change: &Change,
|
||||
data: Vec<Vec<u8>>,
|
||||
fee_rate: Fee,
|
||||
) -> Result<SignableTransaction, TransactionError> {
|
||||
|
|
|
@ -70,7 +70,7 @@ impl SignableTransaction {
|
|||
/// The height is the Monero blockchain height to synchronize around.
|
||||
pub fn multisig(
|
||||
self,
|
||||
keys: ThresholdKeys<Ed25519>,
|
||||
keys: &ThresholdKeys<Ed25519>,
|
||||
mut transcript: RecommendedTranscript,
|
||||
) -> Result<TransactionMachine, TransactionError> {
|
||||
let mut inputs = vec![];
|
||||
|
|
|
@ -241,7 +241,7 @@ macro_rules! test {
|
|||
tx
|
||||
.clone()
|
||||
.multisig(
|
||||
keys[&i].clone(),
|
||||
&keys[&i],
|
||||
RecommendedTranscript::new(b"Monero Serai Test Transaction"),
|
||||
)
|
||||
.unwrap(),
|
||||
|
|
|
@ -63,7 +63,7 @@ impl Client {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn without_connection_pool(host: String) -> Result<Client, Error> {
|
||||
pub fn without_connection_pool(host: &str) -> Result<Client, Error> {
|
||||
Ok(Client {
|
||||
connection: Connection::Connection {
|
||||
connector: Self::connector(),
|
||||
|
|
|
@ -18,7 +18,7 @@ impl Request {
|
|||
|
||||
let mut userpass_iter = userpass.split(':');
|
||||
let username = userpass_iter.next().unwrap().to_string();
|
||||
let password = userpass_iter.next().map(str::to_string).unwrap_or_else(String::new);
|
||||
let password = userpass_iter.next().map_or_else(String::new, str::to_string);
|
||||
zeroize::Zeroize::zeroize(&mut userpass);
|
||||
|
||||
return Ok((username, password));
|
||||
|
|
|
@ -85,13 +85,13 @@ impl FirstPreprocessDb {
|
|||
network: NetworkId,
|
||||
id_type: RecognizedIdType,
|
||||
id: &[u8],
|
||||
preprocess: Vec<Vec<u8>>,
|
||||
preprocess: &Vec<Vec<u8>>,
|
||||
) {
|
||||
if let Some(existing) = FirstPreprocessDb::get(txn, network, id_type, id) {
|
||||
assert_eq!(existing, preprocess, "saved a distinct first preprocess");
|
||||
assert_eq!(&existing, preprocess, "saved a distinct first preprocess");
|
||||
return;
|
||||
}
|
||||
FirstPreprocessDb::set(txn, network, id_type, id, &preprocess);
|
||||
FirstPreprocessDb::set(txn, network, id_type, id, preprocess);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ impl HandoverBatchDb {
|
|||
}
|
||||
}
|
||||
impl QueuedBatchesDb {
|
||||
pub fn queue(txn: &mut impl DbTxn, set: ValidatorSet, batch: Transaction) {
|
||||
pub fn queue(txn: &mut impl DbTxn, set: ValidatorSet, batch: &Transaction) {
|
||||
let mut batches = Self::get(txn, set).unwrap_or_default();
|
||||
batch.write(&mut batches).unwrap();
|
||||
Self::set(txn, set, &batches);
|
||||
|
|
|
@ -159,17 +159,17 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
// We'll only receive these if we fired GenerateKey, which we'll only do if if we're
|
||||
// in-set, making the Tributary relevant
|
||||
ProcessorMessage::KeyGen(inner_msg) => match inner_msg {
|
||||
key_gen::ProcessorMessage::Commitments { id, .. } => Some(id.session),
|
||||
key_gen::ProcessorMessage::InvalidCommitments { id, .. } => Some(id.session),
|
||||
key_gen::ProcessorMessage::Shares { id, .. } => Some(id.session),
|
||||
key_gen::ProcessorMessage::InvalidShare { id, .. } => Some(id.session),
|
||||
key_gen::ProcessorMessage::GeneratedKeyPair { id, .. } => Some(id.session),
|
||||
key_gen::ProcessorMessage::Commitments { id, .. } |
|
||||
key_gen::ProcessorMessage::InvalidCommitments { id, .. } |
|
||||
key_gen::ProcessorMessage::Shares { id, .. } |
|
||||
key_gen::ProcessorMessage::InvalidShare { id, .. } |
|
||||
key_gen::ProcessorMessage::GeneratedKeyPair { id, .. } |
|
||||
key_gen::ProcessorMessage::Blame { id, .. } => Some(id.session),
|
||||
},
|
||||
ProcessorMessage::Sign(inner_msg) => match inner_msg {
|
||||
// We'll only receive InvalidParticipant/Preprocess/Share if we're actively signing
|
||||
sign::ProcessorMessage::InvalidParticipant { id, .. } => Some(id.session),
|
||||
sign::ProcessorMessage::Preprocess { id, .. } => Some(id.session),
|
||||
sign::ProcessorMessage::InvalidParticipant { id, .. } |
|
||||
sign::ProcessorMessage::Preprocess { id, .. } |
|
||||
sign::ProcessorMessage::Share { id, .. } => Some(id.session),
|
||||
// While the Processor's Scanner will always emit Completed, that's routed through the
|
||||
// Signer and only becomes a ProcessorMessage::Completed if the Signer is present and
|
||||
|
@ -233,9 +233,9 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
None
|
||||
}
|
||||
// We'll only fire these if we are the Substrate signer, making the Tributary relevant
|
||||
coordinator::ProcessorMessage::InvalidParticipant { id, .. } => Some(id.session),
|
||||
coordinator::ProcessorMessage::CosignPreprocess { id, .. } => Some(id.session),
|
||||
coordinator::ProcessorMessage::BatchPreprocess { id, .. } => Some(id.session),
|
||||
coordinator::ProcessorMessage::InvalidParticipant { id, .. } |
|
||||
coordinator::ProcessorMessage::CosignPreprocess { id, .. } |
|
||||
coordinator::ProcessorMessage::BatchPreprocess { id, .. } |
|
||||
coordinator::ProcessorMessage::SubstrateShare { id, .. } => Some(id.session),
|
||||
coordinator::ProcessorMessage::CosignedBlock { block_number, block, signature } => {
|
||||
let cosigned_block = CosignedBlock {
|
||||
|
@ -486,7 +486,7 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
network,
|
||||
RecognizedIdType::Plan,
|
||||
&id.id,
|
||||
preprocesses,
|
||||
&preprocesses,
|
||||
);
|
||||
|
||||
vec![]
|
||||
|
@ -566,7 +566,7 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
};
|
||||
id.to_le_bytes()
|
||||
},
|
||||
preprocesses.into_iter().map(Into::into).collect(),
|
||||
&preprocesses.into_iter().map(Into::into).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let intended = Transaction::Batch {
|
||||
|
@ -611,8 +611,7 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
// the prior Batch hasn't been verified yet...
|
||||
if (last_received != 0) &&
|
||||
LastVerifiedBatchDb::get(&txn, msg.network)
|
||||
.map(|last_verified| last_verified < (last_received - 1))
|
||||
.unwrap_or(true)
|
||||
.map_or(true, |last_verified| last_verified < (last_received - 1))
|
||||
{
|
||||
// Withhold this TX until we verify all prior `Batch`s
|
||||
queue = true;
|
||||
|
@ -620,7 +619,7 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
}
|
||||
|
||||
if queue {
|
||||
QueuedBatchesDb::queue(&mut txn, spec.set(), intended);
|
||||
QueuedBatchesDb::queue(&mut txn, spec.set(), &intended);
|
||||
vec![]
|
||||
} else {
|
||||
// Because this is post-verification of the handover batch, take all queued `Batch`s
|
||||
|
@ -650,10 +649,11 @@ async fn handle_processor_message<D: Db, P: P2p>(
|
|||
signed: Transaction::empty_signed(),
|
||||
})]
|
||||
}
|
||||
#[allow(clippy::match_same_arms)] // Allowed to preserve layout
|
||||
coordinator::ProcessorMessage::CosignedBlock { .. } => unreachable!(),
|
||||
},
|
||||
ProcessorMessage::Substrate(inner_msg) => match inner_msg {
|
||||
processor_messages::substrate::ProcessorMessage::Batch { .. } => unreachable!(),
|
||||
processor_messages::substrate::ProcessorMessage::Batch { .. } |
|
||||
processor_messages::substrate::ProcessorMessage::SignedBatch { .. } => unreachable!(),
|
||||
},
|
||||
};
|
||||
|
@ -823,9 +823,8 @@ async fn handle_cosigns_and_batch_publication<D: Db, P: P2p>(
|
|||
let _hvq_lock = HANDOVER_VERIFY_QUEUE_LOCK.get_or_init(|| Mutex::new(())).lock().await;
|
||||
let mut txn = db.txn();
|
||||
let mut to_publish = vec![];
|
||||
let start_id = LastVerifiedBatchDb::get(&txn, network)
|
||||
.map(|already_verified| already_verified + 1)
|
||||
.unwrap_or(0);
|
||||
let start_id =
|
||||
LastVerifiedBatchDb::get(&txn, network).map_or(0, |already_verified| already_verified + 1);
|
||||
if let Some(last_id) =
|
||||
substrate::verify_published_batches::<D>(&mut txn, network, u32::MAX).await
|
||||
{
|
||||
|
@ -847,7 +846,7 @@ async fn handle_cosigns_and_batch_publication<D: Db, P: P2p>(
|
|||
to_publish.push((set.session, queued.remove(0)));
|
||||
// Re-queue the remaining batches
|
||||
for remaining in queued {
|
||||
QueuedBatchesDb::queue(&mut txn, set, remaining);
|
||||
QueuedBatchesDb::queue(&mut txn, set, &remaining);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -59,11 +59,10 @@ pub enum P2pMessageKind {
|
|||
impl P2pMessageKind {
|
||||
fn genesis(&self) -> Option<[u8; 32]> {
|
||||
match self {
|
||||
P2pMessageKind::KeepAlive => None,
|
||||
P2pMessageKind::Tributary(genesis) => Some(*genesis),
|
||||
P2pMessageKind::Heartbeat(genesis) => Some(*genesis),
|
||||
P2pMessageKind::KeepAlive | P2pMessageKind::CosignedBlock => None,
|
||||
P2pMessageKind::Tributary(genesis) |
|
||||
P2pMessageKind::Heartbeat(genesis) |
|
||||
P2pMessageKind::Block(genesis) => Some(*genesis),
|
||||
P2pMessageKind::CosignedBlock => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -303,7 +302,7 @@ impl LibP2p {
|
|||
let mut time_of_last_p2p_message = Instant::now();
|
||||
|
||||
#[allow(clippy::needless_pass_by_ref_mut)] // False positive
|
||||
async fn broadcast_raw(
|
||||
fn broadcast_raw(
|
||||
p2p: &mut Swarm<Behavior>,
|
||||
time_of_last_p2p_message: &mut Instant,
|
||||
genesis: Option<[u8; 32]>,
|
||||
|
@ -364,7 +363,7 @@ impl LibP2p {
|
|||
&mut time_of_last_p2p_message,
|
||||
genesis,
|
||||
msg,
|
||||
).await;
|
||||
);
|
||||
}
|
||||
|
||||
// Handle new incoming messages
|
||||
|
@ -416,7 +415,7 @@ impl LibP2p {
|
|||
&mut time_of_last_p2p_message,
|
||||
None,
|
||||
P2pMessageKind::KeepAlive.serialize()
|
||||
).await;
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -689,16 +688,8 @@ pub async fn handle_p2p_task<D: Db, P: P2p>(
|
|||
let msg = p2p.receive().await;
|
||||
match msg.kind {
|
||||
P2pMessageKind::KeepAlive => {}
|
||||
P2pMessageKind::Tributary(genesis) => {
|
||||
if let Some(channel) = channels.read().await.get(&genesis) {
|
||||
channel.send(msg).unwrap();
|
||||
}
|
||||
}
|
||||
P2pMessageKind::Heartbeat(genesis) => {
|
||||
if let Some(channel) = channels.read().await.get(&genesis) {
|
||||
channel.send(msg).unwrap();
|
||||
}
|
||||
}
|
||||
P2pMessageKind::Tributary(genesis) |
|
||||
P2pMessageKind::Heartbeat(genesis) |
|
||||
P2pMessageKind::Block(genesis) => {
|
||||
if let Some(channel) = channels.read().await.get(&genesis) {
|
||||
channel.send(msg).unwrap();
|
||||
|
|
|
@ -18,7 +18,7 @@ pub use inner_db::{NextBlock, BatchInstructionsHashDb};
|
|||
pub struct HandledEvent;
|
||||
impl HandledEvent {
|
||||
fn next_to_handle_event(getter: &impl Get, block: [u8; 32]) -> u32 {
|
||||
inner_db::HandledEvent::get(getter, block).map(|last| last + 1).unwrap_or(0)
|
||||
inner_db::HandledEvent::get(getter, block).map_or(0, |last| last + 1)
|
||||
}
|
||||
pub fn is_unhandled(getter: &impl Get, block: [u8; 32], event_id: u32) -> bool {
|
||||
let next = Self::next_to_handle_event(getter, block);
|
||||
|
|
|
@ -396,9 +396,8 @@ pub async fn scan_task<D: Db, Pro: Processors>(
|
|||
Ok(latest) => {
|
||||
if latest.header.number >= next_substrate_block {
|
||||
return latest;
|
||||
} else {
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
}
|
||||
sleep(Duration::from_secs(3)).await;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("couldn't communicate with serai node: {e}");
|
||||
|
@ -493,7 +492,7 @@ pub(crate) async fn verify_published_batches<D: Db>(
|
|||
) -> Option<u32> {
|
||||
// TODO: Localize from MainDb to SubstrateDb
|
||||
let last = crate::LastVerifiedBatchDb::get(txn, network);
|
||||
for id in last.map(|last| last + 1).unwrap_or(0) ..= optimistic_up_to {
|
||||
for id in last.map_or(0, |last| last + 1) ..= optimistic_up_to {
|
||||
let Some(on_chain) = BatchInstructionsHashDb::get(txn, network, id) else {
|
||||
break;
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ fn random_sign_data<R: RngCore, Id: Clone + PartialEq + Eq + Debug + Encode + De
|
|||
|
||||
data: {
|
||||
let mut res = vec![];
|
||||
for _ in 0 .. ((rng.next_u64() % 255) + 1) {
|
||||
for _ in 0 ..= (rng.next_u64() % 256) {
|
||||
res.push(random_vec(&mut OsRng, 512));
|
||||
}
|
||||
res
|
||||
|
@ -70,8 +70,8 @@ fn random_sign_data<R: RngCore, Id: Clone + PartialEq + Eq + Debug + Encode + De
|
|||
}
|
||||
}
|
||||
|
||||
fn test_read_write<RW: Eq + Debug + ReadWrite>(value: RW) {
|
||||
assert_eq!(value, RW::read::<&[u8]>(&mut value.serialize().as_ref()).unwrap());
|
||||
fn test_read_write<RW: Eq + Debug + ReadWrite>(value: &RW) {
|
||||
assert_eq!(value, &RW::read::<&[u8]>(&mut value.serialize().as_ref()).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -102,36 +102,36 @@ fn tx_size_limit() {
|
|||
|
||||
#[test]
|
||||
fn serialize_sign_data() {
|
||||
fn test_read_write<Id: Clone + PartialEq + Eq + Debug + Encode + Decode>(value: SignData<Id>) {
|
||||
fn test_read_write<Id: Clone + PartialEq + Eq + Debug + Encode + Decode>(value: &SignData<Id>) {
|
||||
let mut buf = vec![];
|
||||
value.write(&mut buf).unwrap();
|
||||
assert_eq!(value, SignData::read(&mut buf.as_slice()).unwrap())
|
||||
assert_eq!(value, &SignData::read(&mut buf.as_slice()).unwrap())
|
||||
}
|
||||
|
||||
let mut plan = [0; 3];
|
||||
OsRng.fill_bytes(&mut plan);
|
||||
test_read_write(random_sign_data::<_, _>(
|
||||
test_read_write(&random_sign_data::<_, _>(
|
||||
&mut OsRng,
|
||||
plan,
|
||||
if (OsRng.next_u64() % 2) == 0 { Label::Preprocess } else { Label::Share },
|
||||
));
|
||||
let mut plan = [0; 5];
|
||||
OsRng.fill_bytes(&mut plan);
|
||||
test_read_write(random_sign_data::<_, _>(
|
||||
test_read_write(&random_sign_data::<_, _>(
|
||||
&mut OsRng,
|
||||
plan,
|
||||
if (OsRng.next_u64() % 2) == 0 { Label::Preprocess } else { Label::Share },
|
||||
));
|
||||
let mut plan = [0; 8];
|
||||
OsRng.fill_bytes(&mut plan);
|
||||
test_read_write(random_sign_data::<_, _>(
|
||||
test_read_write(&random_sign_data::<_, _>(
|
||||
&mut OsRng,
|
||||
plan,
|
||||
if (OsRng.next_u64() % 2) == 0 { Label::Preprocess } else { Label::Share },
|
||||
));
|
||||
let mut plan = [0; 24];
|
||||
OsRng.fill_bytes(&mut plan);
|
||||
test_read_write(random_sign_data::<_, _>(
|
||||
test_read_write(&random_sign_data::<_, _>(
|
||||
&mut OsRng,
|
||||
plan,
|
||||
if (OsRng.next_u64() % 2) == 0 { Label::Preprocess } else { Label::Share },
|
||||
|
@ -140,7 +140,7 @@ fn serialize_sign_data() {
|
|||
|
||||
#[test]
|
||||
fn serialize_transaction() {
|
||||
test_read_write(Transaction::RemoveParticipantDueToDkg {
|
||||
test_read_write(&Transaction::RemoveParticipantDueToDkg {
|
||||
attempt: u32::try_from(OsRng.next_u64() >> 32).unwrap(),
|
||||
participant: frost::Participant::new(
|
||||
u16::try_from(OsRng.next_u64() >> 48).unwrap().saturating_add(1),
|
||||
|
@ -155,7 +155,7 @@ fn serialize_transaction() {
|
|||
OsRng.fill_bytes(&mut temp);
|
||||
commitments.push(temp);
|
||||
}
|
||||
test_read_write(Transaction::DkgCommitments {
|
||||
test_read_write(&Transaction::DkgCommitments {
|
||||
attempt: random_u32(&mut OsRng),
|
||||
commitments,
|
||||
signed: random_signed_with_nonce(&mut OsRng, 0),
|
||||
|
@ -170,7 +170,7 @@ fn serialize_transaction() {
|
|||
// Create a valid vec of shares
|
||||
let mut shares = vec![];
|
||||
// Create up to 150 participants
|
||||
for _ in 0 .. ((OsRng.next_u64() % 150) + 1) {
|
||||
for _ in 0 ..= (OsRng.next_u64() % 150) {
|
||||
// Give each sender multiple shares
|
||||
let mut sender_shares = vec![];
|
||||
for _ in 0 .. amount_of_shares {
|
||||
|
@ -181,7 +181,7 @@ fn serialize_transaction() {
|
|||
shares.push(sender_shares);
|
||||
}
|
||||
|
||||
test_read_write(Transaction::DkgShares {
|
||||
test_read_write(&Transaction::DkgShares {
|
||||
attempt: random_u32(&mut OsRng),
|
||||
shares,
|
||||
confirmation_nonces: {
|
||||
|
@ -194,7 +194,7 @@ fn serialize_transaction() {
|
|||
}
|
||||
|
||||
for i in 0 .. 2 {
|
||||
test_read_write(Transaction::InvalidDkgShare {
|
||||
test_read_write(&Transaction::InvalidDkgShare {
|
||||
attempt: random_u32(&mut OsRng),
|
||||
accuser: frost::Participant::new(
|
||||
u16::try_from(OsRng.next_u64() >> 48).unwrap().saturating_add(1),
|
||||
|
@ -213,7 +213,7 @@ fn serialize_transaction() {
|
|||
});
|
||||
}
|
||||
|
||||
test_read_write(Transaction::DkgConfirmed {
|
||||
test_read_write(&Transaction::DkgConfirmed {
|
||||
attempt: random_u32(&mut OsRng),
|
||||
confirmation_share: {
|
||||
let mut share = [0; 32];
|
||||
|
@ -226,20 +226,20 @@ fn serialize_transaction() {
|
|||
{
|
||||
let mut block = [0; 32];
|
||||
OsRng.fill_bytes(&mut block);
|
||||
test_read_write(Transaction::CosignSubstrateBlock(block));
|
||||
test_read_write(&Transaction::CosignSubstrateBlock(block));
|
||||
}
|
||||
|
||||
{
|
||||
let mut block = [0; 32];
|
||||
OsRng.fill_bytes(&mut block);
|
||||
let batch = u32::try_from(OsRng.next_u64() >> 32).unwrap();
|
||||
test_read_write(Transaction::Batch { block, batch });
|
||||
test_read_write(&Transaction::Batch { block, batch });
|
||||
}
|
||||
test_read_write(Transaction::SubstrateBlock(OsRng.next_u64()));
|
||||
test_read_write(&Transaction::SubstrateBlock(OsRng.next_u64()));
|
||||
|
||||
{
|
||||
let batch = u32::try_from(OsRng.next_u64() >> 32).unwrap();
|
||||
test_read_write(Transaction::SubstrateSign(random_sign_data(
|
||||
test_read_write(&Transaction::SubstrateSign(random_sign_data(
|
||||
&mut OsRng,
|
||||
SubstrateSignableId::Batch(batch),
|
||||
Label::Preprocess,
|
||||
|
@ -247,7 +247,7 @@ fn serialize_transaction() {
|
|||
}
|
||||
{
|
||||
let batch = u32::try_from(OsRng.next_u64() >> 32).unwrap();
|
||||
test_read_write(Transaction::SubstrateSign(random_sign_data(
|
||||
test_read_write(&Transaction::SubstrateSign(random_sign_data(
|
||||
&mut OsRng,
|
||||
SubstrateSignableId::Batch(batch),
|
||||
Label::Share,
|
||||
|
@ -257,12 +257,12 @@ fn serialize_transaction() {
|
|||
{
|
||||
let mut plan = [0; 32];
|
||||
OsRng.fill_bytes(&mut plan);
|
||||
test_read_write(Transaction::Sign(random_sign_data(&mut OsRng, plan, Label::Preprocess)));
|
||||
test_read_write(&Transaction::Sign(random_sign_data(&mut OsRng, plan, Label::Preprocess)));
|
||||
}
|
||||
{
|
||||
let mut plan = [0; 32];
|
||||
OsRng.fill_bytes(&mut plan);
|
||||
test_read_write(Transaction::Sign(random_sign_data(&mut OsRng, plan, Label::Share)));
|
||||
test_read_write(&Transaction::Sign(random_sign_data(&mut OsRng, plan, Label::Share)));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -270,7 +270,7 @@ fn serialize_transaction() {
|
|||
OsRng.fill_bytes(&mut plan);
|
||||
let mut tx_hash = vec![0; (OsRng.next_u64() % 64).try_into().unwrap()];
|
||||
OsRng.fill_bytes(&mut tx_hash);
|
||||
test_read_write(Transaction::SignCompleted {
|
||||
test_read_write(&Transaction::SignCompleted {
|
||||
plan,
|
||||
tx_hash,
|
||||
first_signer: random_signed_with_nonce(&mut OsRng, 2).signer,
|
||||
|
|
|
@ -204,18 +204,18 @@ impl<
|
|||
Accumulation::NotReady
|
||||
}
|
||||
|
||||
async fn handle_data(
|
||||
fn handle_data(
|
||||
&mut self,
|
||||
removed: &[<Ristretto as Ciphersuite>::G],
|
||||
data_spec: &DataSpecification,
|
||||
bytes: Vec<u8>,
|
||||
bytes: &Vec<u8>,
|
||||
signed: &Signed,
|
||||
) -> Accumulation {
|
||||
let genesis = self.spec.genesis();
|
||||
|
||||
let Some(curr_attempt) = AttemptDb::attempt(self.txn, genesis, data_spec.topic) else {
|
||||
// Premature publication of a valid ID/publication of an invalid ID
|
||||
self.fatal_slash(signed.signer.to_bytes(), "published data for ID without an attempt").await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "published data for ID without an attempt");
|
||||
return Accumulation::NotReady;
|
||||
};
|
||||
|
||||
|
@ -223,7 +223,7 @@ impl<
|
|||
// This shouldn't be reachable since nonces were made inserted by the coordinator, yet it's a
|
||||
// cheap check to leave in for safety
|
||||
if DataDb::get(self.txn, genesis, data_spec, &signed.signer.to_bytes()).is_some() {
|
||||
self.fatal_slash(signed.signer.to_bytes(), "published data multiple times").await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "published data multiple times");
|
||||
return Accumulation::NotReady;
|
||||
}
|
||||
|
||||
|
@ -239,12 +239,10 @@ impl<
|
|||
}
|
||||
// If the attempt is greater, this is a premature publication, full slash
|
||||
if data_spec.attempt > curr_attempt {
|
||||
self
|
||||
.fatal_slash(
|
||||
signed.signer.to_bytes(),
|
||||
"published data with an attempt which hasn't started",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
signed.signer.to_bytes(),
|
||||
"published data with an attempt which hasn't started",
|
||||
);
|
||||
return Accumulation::NotReady;
|
||||
}
|
||||
|
||||
|
@ -254,10 +252,10 @@ impl<
|
|||
// TODO: If this is shares, we need to check they are part of the selected signing set
|
||||
|
||||
// Accumulate this data
|
||||
self.accumulate(removed, data_spec, signed.signer, &bytes)
|
||||
self.accumulate(removed, data_spec, signed.signer, bytes)
|
||||
}
|
||||
|
||||
async fn check_sign_data_len(
|
||||
fn check_sign_data_len(
|
||||
&mut self,
|
||||
removed: &[<Ristretto as Ciphersuite>::G],
|
||||
signer: <Ristretto as Ciphersuite>::G,
|
||||
|
@ -265,12 +263,10 @@ impl<
|
|||
) -> Result<(), ()> {
|
||||
let signer_i = self.spec.i(removed, signer).unwrap();
|
||||
if len != usize::from(u16::from(signer_i.end) - u16::from(signer_i.start)) {
|
||||
self
|
||||
.fatal_slash(
|
||||
signer.to_bytes(),
|
||||
"signer published a distinct amount of sign data than they had shares",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
signer.to_bytes(),
|
||||
"signer published a distinct amount of sign data than they had shares",
|
||||
);
|
||||
Err(())?;
|
||||
}
|
||||
Ok(())
|
||||
|
@ -292,34 +288,28 @@ impl<
|
|||
}
|
||||
|
||||
match tx {
|
||||
Transaction::RemoveParticipantDueToDkg { attempt, participant } => {
|
||||
self
|
||||
.fatal_slash_with_participant_index(
|
||||
&removed_as_of_dkg_attempt(self.txn, genesis, attempt).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"removed a participant due to a provided transaction with an attempt not {}",
|
||||
"locally handled?"
|
||||
)
|
||||
}),
|
||||
participant,
|
||||
"RemoveParticipantDueToDkg Provided TX",
|
||||
)
|
||||
.await
|
||||
}
|
||||
Transaction::RemoveParticipantDueToDkg { attempt, participant } => self
|
||||
.fatal_slash_with_participant_index(
|
||||
&removed_as_of_dkg_attempt(self.txn, genesis, attempt).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"removed a participant due to a provided transaction with an attempt not {}",
|
||||
"locally handled?"
|
||||
)
|
||||
}),
|
||||
participant,
|
||||
"RemoveParticipantDueToDkg Provided TX",
|
||||
),
|
||||
|
||||
Transaction::DkgCommitments { attempt, commitments, signed } => {
|
||||
let Some(removed) = removed_as_of_dkg_attempt(self.txn, genesis, attempt) else {
|
||||
self
|
||||
.fatal_slash(signed.signer.to_bytes(), "DkgCommitments with an unrecognized attempt")
|
||||
.await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "DkgCommitments with an unrecognized attempt");
|
||||
return;
|
||||
};
|
||||
let Ok(()) = self.check_sign_data_len(&removed, signed.signer, commitments.len()).await
|
||||
else {
|
||||
let Ok(()) = self.check_sign_data_len(&removed, signed.signer, commitments.len()) else {
|
||||
return;
|
||||
};
|
||||
let data_spec = DataSpecification { topic: Topic::Dkg, label: Label::Preprocess, attempt };
|
||||
match self.handle_data(&removed, &data_spec, commitments.encode(), &signed).await {
|
||||
match self.handle_data(&removed, &data_spec, &commitments.encode(), &signed) {
|
||||
Accumulation::Ready(DataSet::Participating(mut commitments)) => {
|
||||
log::info!("got all DkgCommitments for {}", hex::encode(genesis));
|
||||
unflatten(self.spec, &removed, &mut commitments);
|
||||
|
@ -343,12 +333,10 @@ impl<
|
|||
|
||||
Transaction::DkgShares { attempt, mut shares, confirmation_nonces, signed } => {
|
||||
let Some(removed) = removed_as_of_dkg_attempt(self.txn, genesis, attempt) else {
|
||||
self
|
||||
.fatal_slash(signed.signer.to_bytes(), "DkgShares with an unrecognized attempt")
|
||||
.await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "DkgShares with an unrecognized attempt");
|
||||
return;
|
||||
};
|
||||
let Ok(()) = self.check_sign_data_len(&removed, signed.signer, shares.len()).await else {
|
||||
let Ok(()) = self.check_sign_data_len(&removed, signed.signer, shares.len()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -359,7 +347,7 @@ impl<
|
|||
let sender_is_len = u16::from(sender_i.end) - u16::from(sender_i.start);
|
||||
for shares in &shares {
|
||||
if shares.len() != (usize::from(self.spec.n(&removed) - sender_is_len)) {
|
||||
self.fatal_slash(signed.signer.to_bytes(), "invalid amount of DKG shares").await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "invalid amount of DKG shares");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -419,7 +407,7 @@ impl<
|
|||
|
||||
let data_spec = DataSpecification { topic: Topic::Dkg, label: Label::Share, attempt };
|
||||
let encoded_data = (confirmation_nonces.to_vec(), our_shares.encode()).encode();
|
||||
match self.handle_data(&removed, &data_spec, encoded_data, &signed).await {
|
||||
match self.handle_data(&removed, &data_spec, &encoded_data, &signed) {
|
||||
Accumulation::Ready(DataSet::Participating(confirmation_nonces_and_shares)) => {
|
||||
log::info!("got all DkgShares for {}", hex::encode(genesis));
|
||||
|
||||
|
@ -479,34 +467,27 @@ impl<
|
|||
Transaction::InvalidDkgShare { attempt, accuser, faulty, blame, signed } => {
|
||||
let Some(removed) = removed_as_of_dkg_attempt(self.txn, genesis, attempt) else {
|
||||
self
|
||||
.fatal_slash(signed.signer.to_bytes(), "InvalidDkgShare with an unrecognized attempt")
|
||||
.await;
|
||||
.fatal_slash(signed.signer.to_bytes(), "InvalidDkgShare with an unrecognized attempt");
|
||||
return;
|
||||
};
|
||||
let range = self.spec.i(&removed, signed.signer).unwrap();
|
||||
if !range.contains(&accuser) {
|
||||
self
|
||||
.fatal_slash(
|
||||
signed.signer.to_bytes(),
|
||||
"accused with a Participant index which wasn't theirs",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
signed.signer.to_bytes(),
|
||||
"accused with a Participant index which wasn't theirs",
|
||||
);
|
||||
return;
|
||||
}
|
||||
if range.contains(&faulty) {
|
||||
self
|
||||
.fatal_slash(signed.signer.to_bytes(), "accused self of having an InvalidDkgShare")
|
||||
.await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "accused self of having an InvalidDkgShare");
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(share) = DkgShare::get(self.txn, genesis, accuser.into(), faulty.into()) else {
|
||||
self
|
||||
.fatal_slash(
|
||||
signed.signer.to_bytes(),
|
||||
"InvalidDkgShare had a non-existent faulty participant",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
signed.signer.to_bytes(),
|
||||
"InvalidDkgShare had a non-existent faulty participant",
|
||||
);
|
||||
return;
|
||||
};
|
||||
self
|
||||
|
@ -526,15 +507,13 @@ impl<
|
|||
|
||||
Transaction::DkgConfirmed { attempt, confirmation_share, signed } => {
|
||||
let Some(removed) = removed_as_of_dkg_attempt(self.txn, genesis, attempt) else {
|
||||
self
|
||||
.fatal_slash(signed.signer.to_bytes(), "DkgConfirmed with an unrecognized attempt")
|
||||
.await;
|
||||
self.fatal_slash(signed.signer.to_bytes(), "DkgConfirmed with an unrecognized attempt");
|
||||
return;
|
||||
};
|
||||
|
||||
let data_spec =
|
||||
DataSpecification { topic: Topic::DkgConfirmation, label: Label::Share, attempt };
|
||||
match self.handle_data(&removed, &data_spec, confirmation_share.to_vec(), &signed).await {
|
||||
match self.handle_data(&removed, &data_spec, &confirmation_share.to_vec(), &signed) {
|
||||
Accumulation::Ready(DataSet::Participating(shares)) => {
|
||||
log::info!("got all DkgConfirmed for {}", hex::encode(genesis));
|
||||
|
||||
|
@ -556,9 +535,7 @@ impl<
|
|||
let sig = match confirmer.complete(preprocesses, &key_pair, shares) {
|
||||
Ok(sig) => sig,
|
||||
Err(p) => {
|
||||
self
|
||||
.fatal_slash_with_participant_index(&removed, p, "invalid DkgConfirmer share")
|
||||
.await;
|
||||
self.fatal_slash_with_participant_index(&removed, p, "invalid DkgConfirmer share");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -641,16 +618,14 @@ impl<
|
|||
let Some(removed) =
|
||||
crate::tributary::removed_as_of_set_keys(self.txn, self.spec.set(), genesis)
|
||||
else {
|
||||
self
|
||||
.fatal_slash(
|
||||
data.signed.signer.to_bytes(),
|
||||
"signing despite not having set keys on substrate",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
data.signed.signer.to_bytes(),
|
||||
"signing despite not having set keys on substrate",
|
||||
);
|
||||
return;
|
||||
};
|
||||
let signer = data.signed.signer;
|
||||
let Ok(()) = self.check_sign_data_len(&removed, signer, data.data.len()).await else {
|
||||
let Ok(()) = self.check_sign_data_len(&removed, signer, data.data.len()) else {
|
||||
return;
|
||||
};
|
||||
let expected_len = match data.label {
|
||||
|
@ -659,12 +634,10 @@ impl<
|
|||
};
|
||||
for data in &data.data {
|
||||
if data.len() != expected_len {
|
||||
self
|
||||
.fatal_slash(
|
||||
signer.to_bytes(),
|
||||
"unexpected length data for substrate signing protocol",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
signer.to_bytes(),
|
||||
"unexpected length data for substrate signing protocol",
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +648,7 @@ impl<
|
|||
attempt: data.attempt,
|
||||
};
|
||||
let Accumulation::Ready(DataSet::Participating(mut results)) =
|
||||
self.handle_data(&removed, &data_spec, data.data.encode(), &data.signed).await
|
||||
self.handle_data(&removed, &data_spec, &data.data.encode(), &data.signed)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
@ -703,16 +676,13 @@ impl<
|
|||
let Some(removed) =
|
||||
crate::tributary::removed_as_of_set_keys(self.txn, self.spec.set(), genesis)
|
||||
else {
|
||||
self
|
||||
.fatal_slash(
|
||||
data.signed.signer.to_bytes(),
|
||||
"signing despite not having set keys on substrate",
|
||||
)
|
||||
.await;
|
||||
self.fatal_slash(
|
||||
data.signed.signer.to_bytes(),
|
||||
"signing despite not having set keys on substrate",
|
||||
);
|
||||
return;
|
||||
};
|
||||
let Ok(()) = self.check_sign_data_len(&removed, data.signed.signer, data.data.len()).await
|
||||
else {
|
||||
let Ok(()) = self.check_sign_data_len(&removed, data.signed.signer, data.data.len()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -722,7 +692,7 @@ impl<
|
|||
attempt: data.attempt,
|
||||
};
|
||||
if let Accumulation::Ready(DataSet::Participating(mut results)) =
|
||||
self.handle_data(&removed, &data_spec, data.data.encode(), &data.signed).await
|
||||
self.handle_data(&removed, &data_spec, &data.data.encode(), &data.signed)
|
||||
{
|
||||
unflatten(self.spec, &removed, &mut results);
|
||||
let id =
|
||||
|
@ -750,9 +720,7 @@ impl<
|
|||
);
|
||||
|
||||
if AttemptDb::attempt(self.txn, genesis, Topic::Sign(plan)).is_none() {
|
||||
self
|
||||
.fatal_slash(first_signer.to_bytes(), "claimed an unrecognized plan was completed")
|
||||
.await;
|
||||
self.fatal_slash(first_signer.to_bytes(), "claimed an unrecognized plan was completed");
|
||||
return;
|
||||
};
|
||||
|
||||
|
|
|
@ -192,7 +192,7 @@ impl<
|
|||
P: P2p,
|
||||
> TributaryBlockHandler<'_, T, Pro, PST, PTT, RID, P>
|
||||
{
|
||||
pub async fn fatal_slash(&mut self, slashing: [u8; 32], reason: &str) {
|
||||
pub fn fatal_slash(&mut self, slashing: [u8; 32], reason: &str) {
|
||||
// TODO: If this fatal slash puts the remaining set below the threshold, spin
|
||||
|
||||
let genesis = self.spec.genesis();
|
||||
|
@ -209,7 +209,7 @@ impl<
|
|||
// Tributary post-DKG
|
||||
// https://github.com/serai-dex/serai/issues/426
|
||||
|
||||
pub async fn fatal_slash_with_participant_index(
|
||||
pub fn fatal_slash_with_participant_index(
|
||||
&mut self,
|
||||
removed: &[<Ristretto as Ciphersuite>::G],
|
||||
i: Participant,
|
||||
|
@ -227,7 +227,7 @@ impl<
|
|||
}
|
||||
let validator = validator.unwrap();
|
||||
|
||||
self.fatal_slash(validator.to_bytes(), reason).await;
|
||||
self.fatal_slash(validator.to_bytes(), reason);
|
||||
}
|
||||
|
||||
async fn handle<D: Db>(mut self) {
|
||||
|
@ -240,10 +240,9 @@ impl<
|
|||
// Since the evidence is on the chain, it should already have been validated
|
||||
// We can just punish the signer
|
||||
let data = match ev {
|
||||
Evidence::ConflictingMessages(first, second) => (first, Some(second)),
|
||||
Evidence::ConflictingMessages(first, second) |
|
||||
Evidence::ConflictingPrecommit(first, second) => (first, Some(second)),
|
||||
Evidence::InvalidPrecommit(first) => (first, None),
|
||||
Evidence::InvalidValidRound(first) => (first, None),
|
||||
Evidence::InvalidPrecommit(first) | Evidence::InvalidValidRound(first) => (first, None),
|
||||
};
|
||||
let msgs = (
|
||||
decode_signed_message::<TendermintNetwork<D, Transaction, P>>(&data.0).unwrap(),
|
||||
|
@ -259,9 +258,7 @@ impl<
|
|||
|
||||
// Since anything with evidence is fundamentally faulty behavior, not just temporal
|
||||
// errors, mark the node as fatally slashed
|
||||
self
|
||||
.fatal_slash(msgs.0.msg.sender, &format!("invalid tendermint messages: {:?}", msgs))
|
||||
.await;
|
||||
self.fatal_slash(msgs.0.msg.sender, &format!("invalid tendermint messages: {msgs:?}"));
|
||||
}
|
||||
TributaryTransaction::Application(tx) => {
|
||||
self.handle_application_tx(tx).await;
|
||||
|
@ -348,8 +345,7 @@ impl<
|
|||
// Check if the cosigner has a signature from our set for this block/a newer one
|
||||
let latest_cosign =
|
||||
crate::cosign_evaluator::LatestCosign::get(self.txn, self.spec.set().network)
|
||||
.map(|cosign| cosign.block_number)
|
||||
.unwrap_or(0);
|
||||
.map_or(0, |cosign| cosign.block_number);
|
||||
if latest_cosign < block_number {
|
||||
// Instruct the processor to start the next attempt
|
||||
self
|
||||
|
|
|
@ -184,7 +184,6 @@ impl<T: DbTxn, C: Encode> SigningProtocol<'_, T, C> {
|
|||
}
|
||||
|
||||
fn complete_internal(
|
||||
&mut self,
|
||||
machine: AlgorithmSignatureMachine<Ristretto, Schnorrkel>,
|
||||
shares: HashMap<Participant, Vec<u8>>,
|
||||
) -> Result<[u8; 64], Participant> {
|
||||
|
@ -251,6 +250,8 @@ fn threshold_i_map_to_keys_and_musig_i_map(
|
|||
(participants, map)
|
||||
}
|
||||
|
||||
type DkgConfirmerSigningProtocol<'a, T> = SigningProtocol<'a, T, (&'static [u8; 12], u32)>;
|
||||
|
||||
pub(crate) struct DkgConfirmer<'a, T: DbTxn> {
|
||||
key: &'a Zeroizing<<Ristretto as Ciphersuite>::F>,
|
||||
spec: &'a TributarySpec,
|
||||
|
@ -271,7 +272,7 @@ impl<T: DbTxn> DkgConfirmer<'_, T> {
|
|||
let removed = crate::tributary::removed_as_of_dkg_attempt(txn, spec.genesis(), attempt)?;
|
||||
Some(DkgConfirmer { key, spec, removed, txn, attempt })
|
||||
}
|
||||
fn signing_protocol(&mut self) -> SigningProtocol<'_, T, (&'static [u8; 12], u32)> {
|
||||
fn signing_protocol(&mut self) -> DkgConfirmerSigningProtocol<'_, T> {
|
||||
let context = (b"DkgConfirmer", self.attempt);
|
||||
SigningProtocol { key: self.key, spec: self.spec, txn: self.txn, context }
|
||||
}
|
||||
|
@ -323,6 +324,6 @@ impl<T: DbTxn> DkgConfirmer<'_, T> {
|
|||
.expect("trying to complete a machine which failed to preprocess")
|
||||
.0;
|
||||
|
||||
self.signing_protocol().complete_internal(machine, shares)
|
||||
DkgConfirmerSigningProtocol::<'_, T>::complete_internal(machine, shares)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@ impl ReadWrite for Transaction {
|
|||
writer.write_all(&u16::from(*faulty).to_le_bytes())?;
|
||||
|
||||
// Flattens Some(vec![]) to None on the expectation no actual blame will be 0-length
|
||||
assert!(blame.as_ref().map(|blame| blame.len()).unwrap_or(1) != 0);
|
||||
assert!(blame.as_ref().map_or(1, Vec::len) != 0);
|
||||
let blame_len =
|
||||
u16::try_from(blame.as_ref().unwrap_or(&vec![]).len()).expect("blame exceeded 64 KB");
|
||||
writer.write_all(&blame_len.to_le_bytes())?;
|
||||
|
@ -547,15 +547,9 @@ impl TransactionTrait for Transaction {
|
|||
match self {
|
||||
Transaction::RemoveParticipantDueToDkg { .. } => TransactionKind::Provided("remove"),
|
||||
|
||||
Transaction::DkgCommitments { attempt, commitments: _, signed } => {
|
||||
TransactionKind::Signed((b"dkg", attempt).encode(), signed)
|
||||
}
|
||||
Transaction::DkgShares { attempt, signed, .. } => {
|
||||
TransactionKind::Signed((b"dkg", attempt).encode(), signed)
|
||||
}
|
||||
Transaction::InvalidDkgShare { attempt, signed, .. } => {
|
||||
TransactionKind::Signed((b"dkg", attempt).encode(), signed)
|
||||
}
|
||||
Transaction::DkgCommitments { attempt, commitments: _, signed } |
|
||||
Transaction::DkgShares { attempt, signed, .. } |
|
||||
Transaction::InvalidDkgShare { attempt, signed, .. } |
|
||||
Transaction::DkgConfirmed { attempt, signed, .. } => {
|
||||
TransactionKind::Signed((b"dkg", attempt).encode(), signed)
|
||||
}
|
||||
|
@ -625,8 +619,7 @@ impl Transaction {
|
|||
|
||||
Transaction::DkgCommitments { .. } => 0,
|
||||
Transaction::DkgShares { .. } => 1,
|
||||
Transaction::InvalidDkgShare { .. } => 2,
|
||||
Transaction::DkgConfirmed { .. } => 2,
|
||||
Transaction::InvalidDkgShare { .. } | Transaction::DkgConfirmed { .. } => 2,
|
||||
|
||||
Transaction::CosignSubstrateBlock(_) => panic!("signing CosignSubstrateBlock"),
|
||||
|
||||
|
@ -635,6 +628,7 @@ impl Transaction {
|
|||
|
||||
Transaction::SubstrateSign(data) => data.label.nonce(),
|
||||
Transaction::Sign(data) => data.label.nonce(),
|
||||
|
||||
Transaction::SignCompleted { .. } => panic!("signing SignCompleted"),
|
||||
};
|
||||
|
||||
|
@ -643,9 +637,9 @@ impl Transaction {
|
|||
match tx {
|
||||
Transaction::RemoveParticipantDueToDkg { .. } => panic!("signing RemoveParticipant"),
|
||||
|
||||
Transaction::DkgCommitments { ref mut signed, .. } => signed,
|
||||
Transaction::DkgShares { ref mut signed, .. } => signed,
|
||||
Transaction::InvalidDkgShare { ref mut signed, .. } => signed,
|
||||
Transaction::DkgCommitments { ref mut signed, .. } |
|
||||
Transaction::DkgShares { ref mut signed, .. } |
|
||||
Transaction::InvalidDkgShare { ref mut signed, .. } |
|
||||
Transaction::DkgConfirmed { ref mut signed, .. } => signed,
|
||||
|
||||
Transaction::CosignSubstrateBlock(_) => panic!("signing CosignSubstrateBlock"),
|
||||
|
@ -655,6 +649,7 @@ impl Transaction {
|
|||
|
||||
Transaction::SubstrateSign(ref mut data) => &mut data.signed,
|
||||
Transaction::Sign(ref mut data) => &mut data.signed,
|
||||
|
||||
Transaction::SignCompleted { .. } => panic!("signing SignCompleted"),
|
||||
},
|
||||
)
|
||||
|
|
|
@ -174,7 +174,7 @@ impl<T: TransactionTrait> Block<T> {
|
|||
last_block: [u8; 32],
|
||||
mut locally_provided: HashMap<&'static str, VecDeque<T>>,
|
||||
get_and_increment_nonce: &mut G,
|
||||
schema: N::SignatureScheme,
|
||||
schema: &N::SignatureScheme,
|
||||
commit: impl Fn(u32) -> Option<Commit<N::SignatureScheme>>,
|
||||
unsigned_in_chain: impl Fn([u8; 32]) -> bool,
|
||||
provided_in_chain: impl Fn([u8; 32]) -> bool, // TODO: merge this with unsigned_on_chain?
|
||||
|
@ -217,7 +217,7 @@ impl<T: TransactionTrait> Block<T> {
|
|||
Err(BlockError::ProvidedAlreadyIncluded)?;
|
||||
}
|
||||
|
||||
if let Some(local) = locally_provided.get_mut(order).and_then(|deque| deque.pop_front()) {
|
||||
if let Some(local) = locally_provided.get_mut(order).and_then(VecDeque::pop_front) {
|
||||
// Since this was a provided TX, it must be an application TX
|
||||
let Transaction::Application(tx) = tx else {
|
||||
Err(BlockError::NonLocalProvided(txs.pop().unwrap()))?
|
||||
|
@ -250,12 +250,10 @@ impl<T: TransactionTrait> Block<T> {
|
|||
last_tx_order = current_tx_order;
|
||||
|
||||
match tx {
|
||||
Transaction::Tendermint(tx) => {
|
||||
match verify_tendermint_tx::<N>(tx, schema.clone(), &commit) {
|
||||
Ok(()) => {}
|
||||
Err(e) => Err(BlockError::TransactionError(e))?,
|
||||
}
|
||||
}
|
||||
Transaction::Tendermint(tx) => match verify_tendermint_tx::<N>(tx, schema, &commit) {
|
||||
Ok(()) => {}
|
||||
Err(e) => Err(BlockError::TransactionError(e))?,
|
||||
},
|
||||
Transaction::Application(tx) => {
|
||||
match verify_transaction(tx, genesis, get_and_increment_nonce) {
|
||||
Ok(()) => {}
|
||||
|
|
|
@ -139,25 +139,23 @@ impl<D: Db, T: TransactionTrait> Blockchain<D, T> {
|
|||
order: &str,
|
||||
) -> bool {
|
||||
let local_key = ProvidedTransactions::<D, T>::locally_provided_quantity_key(genesis, order);
|
||||
let local =
|
||||
db.get(local_key).map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())).unwrap_or(0);
|
||||
let local = db.get(local_key).map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap()));
|
||||
let block_key =
|
||||
ProvidedTransactions::<D, T>::block_provided_quantity_key(genesis, block, order);
|
||||
let block =
|
||||
db.get(block_key).map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap())).unwrap_or(0);
|
||||
let block = db.get(block_key).map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap()));
|
||||
|
||||
local >= block
|
||||
}
|
||||
|
||||
pub(crate) fn tip_from_db(db: &D, genesis: [u8; 32]) -> [u8; 32] {
|
||||
db.get(Self::tip_key(genesis)).map(|bytes| bytes.try_into().unwrap()).unwrap_or(genesis)
|
||||
db.get(Self::tip_key(genesis)).map_or(genesis, |bytes| bytes.try_into().unwrap())
|
||||
}
|
||||
|
||||
pub(crate) fn add_transaction<N: Network>(
|
||||
&mut self,
|
||||
internal: bool,
|
||||
tx: Transaction<T>,
|
||||
schema: N::SignatureScheme,
|
||||
schema: &N::SignatureScheme,
|
||||
) -> Result<bool, TransactionError> {
|
||||
let db = self.db.as_ref().unwrap();
|
||||
let genesis = self.genesis;
|
||||
|
@ -177,8 +175,7 @@ impl<D: Db, T: TransactionTrait> Blockchain<D, T> {
|
|||
if self.participants.contains(&signer) {
|
||||
Some(
|
||||
db.get(Self::next_nonce_key(&self.genesis, &signer, &order))
|
||||
.map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))
|
||||
.unwrap_or(0),
|
||||
.map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap())),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
@ -211,15 +208,14 @@ impl<D: Db, T: TransactionTrait> Blockchain<D, T> {
|
|||
.as_ref()
|
||||
.unwrap()
|
||||
.get(Self::next_nonce_key(&self.genesis, signer, order))
|
||||
.map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))
|
||||
.unwrap_or(0),
|
||||
.map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap())),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_block<N: Network>(&mut self, schema: N::SignatureScheme) -> Block<T> {
|
||||
pub(crate) fn build_block<N: Network>(&mut self, schema: &N::SignatureScheme) -> Block<T> {
|
||||
let block = Block::new(
|
||||
self.tip,
|
||||
self.provided.transactions.values().flatten().cloned().collect(),
|
||||
|
@ -233,7 +229,7 @@ impl<D: Db, T: TransactionTrait> Blockchain<D, T> {
|
|||
pub(crate) fn verify_block<N: Network>(
|
||||
&self,
|
||||
block: &Block<T>,
|
||||
schema: N::SignatureScheme,
|
||||
schema: &N::SignatureScheme,
|
||||
allow_non_local_provided: bool,
|
||||
) -> Result<(), BlockError> {
|
||||
let db = self.db.as_ref().unwrap();
|
||||
|
@ -258,8 +254,7 @@ impl<D: Db, T: TransactionTrait> Blockchain<D, T> {
|
|||
let key = Self::next_nonce_key(&self.genesis, signer, order);
|
||||
let next = txn
|
||||
.get(&key)
|
||||
.map(|next_nonce| u32::from_le_bytes(next_nonce.try_into().unwrap()))
|
||||
.unwrap_or(0);
|
||||
.map_or(0, |next_nonce| u32::from_le_bytes(next_nonce.try_into().unwrap()));
|
||||
txn.put(key, (next + 1).to_le_bytes());
|
||||
Some(next)
|
||||
} else {
|
||||
|
@ -282,7 +277,7 @@ impl<D: Db, T: TransactionTrait> Blockchain<D, T> {
|
|||
&mut self,
|
||||
block: &Block<T>,
|
||||
commit: Vec<u8>,
|
||||
schema: N::SignatureScheme,
|
||||
schema: &N::SignatureScheme,
|
||||
) -> Result<(), BlockError> {
|
||||
self.verify_block::<N>(block, schema, true)?;
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Tributary<D, T, P> {
|
|||
start_time
|
||||
};
|
||||
let proposal = TendermintBlock(
|
||||
blockchain.build_block::<TendermintNetwork<D, T, P>>(validators.clone()).serialize(),
|
||||
blockchain.build_block::<TendermintNetwork<D, T, P>>(&validators).serialize(),
|
||||
);
|
||||
let blockchain = Arc::new(RwLock::new(blockchain));
|
||||
|
||||
|
@ -273,7 +273,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Tributary<D, T, P> {
|
|||
let res = self.network.blockchain.write().await.add_transaction::<TendermintNetwork<D, T, P>>(
|
||||
true,
|
||||
tx,
|
||||
self.network.signature_scheme(),
|
||||
&self.network.signature_scheme(),
|
||||
);
|
||||
if res == Ok(true) {
|
||||
self.network.p2p.broadcast(self.genesis, to_broadcast).await;
|
||||
|
@ -344,7 +344,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Tributary<D, T, P> {
|
|||
self.network.blockchain.write().await.add_transaction::<TendermintNetwork<D, T, P>>(
|
||||
false,
|
||||
tx,
|
||||
self.network.signature_scheme(),
|
||||
&self.network.signature_scheme(),
|
||||
);
|
||||
log::debug!("received transaction message. valid new transaction: {res:?}");
|
||||
res == Ok(true)
|
||||
|
|
|
@ -112,7 +112,7 @@ impl<D: Db, T: TransactionTrait> Mempool<D, T> {
|
|||
blockchain_next_nonce: F,
|
||||
internal: bool,
|
||||
tx: Transaction<T>,
|
||||
schema: N::SignatureScheme,
|
||||
schema: &N::SignatureScheme,
|
||||
unsigned_in_chain: impl Fn([u8; 32]) -> bool,
|
||||
commit: impl Fn(u32) -> Option<Commit<N::SignatureScheme>>,
|
||||
) -> Result<bool, TransactionError> {
|
||||
|
|
|
@ -17,13 +17,7 @@ pub(crate) fn merkle(hash_args: &[[u8; 32]]) -> [u8; 32] {
|
|||
[
|
||||
b"branch_hash".as_ref(),
|
||||
hashes[i].as_ref(),
|
||||
hashes
|
||||
.get(i + 1)
|
||||
.map(|hash| {
|
||||
let res: &[u8] = hash.as_ref();
|
||||
res
|
||||
})
|
||||
.unwrap_or(zero.as_ref()),
|
||||
hashes.get(i + 1).map_or(zero.as_ref(), AsRef::as_ref),
|
||||
]
|
||||
.concat(),
|
||||
));
|
||||
|
@ -33,5 +27,5 @@ pub(crate) fn merkle(hash_args: &[[u8; 32]]) -> [u8; 32] {
|
|||
hashes = interim;
|
||||
}
|
||||
|
||||
hashes.first().copied().map(Into::into).unwrap_or(zero)
|
||||
hashes.first().copied().map_or(zero, Into::into)
|
||||
}
|
||||
|
|
|
@ -103,17 +103,11 @@ impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
|||
|
||||
// get local and on-chain tx numbers
|
||||
let local_key = Self::locally_provided_quantity_key(&self.genesis, order);
|
||||
let mut local_quantity = self
|
||||
.db
|
||||
.get(&local_key)
|
||||
.map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))
|
||||
.unwrap_or(0);
|
||||
let mut local_quantity =
|
||||
self.db.get(&local_key).map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap()));
|
||||
let on_chain_key = Self::on_chain_provided_quantity_key(&self.genesis, order);
|
||||
let on_chain_quantity = self
|
||||
.db
|
||||
.get(on_chain_key)
|
||||
.map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))
|
||||
.unwrap_or(0);
|
||||
let on_chain_quantity =
|
||||
self.db.get(on_chain_key).map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap()));
|
||||
|
||||
let current_provided_key = self.current_provided_key();
|
||||
|
||||
|
@ -158,7 +152,7 @@ impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
|||
block: [u8; 32],
|
||||
tx: [u8; 32],
|
||||
) {
|
||||
if let Some(next_tx) = self.transactions.get_mut(order).and_then(|queue| queue.pop_front()) {
|
||||
if let Some(next_tx) = self.transactions.get_mut(order).and_then(VecDeque::pop_front) {
|
||||
assert_eq!(next_tx.hash(), tx);
|
||||
|
||||
let current_provided_key = self.current_provided_key();
|
||||
|
@ -184,11 +178,8 @@ impl<D: Db, T: Transaction> ProvidedTransactions<D, T> {
|
|||
// bump the on-chain tx number.
|
||||
let on_chain_key = Self::on_chain_provided_quantity_key(&self.genesis, order);
|
||||
let block_order_key = Self::block_provided_quantity_key(&self.genesis, &block, order);
|
||||
let mut on_chain_quantity = self
|
||||
.db
|
||||
.get(&on_chain_key)
|
||||
.map(|bytes| u32::from_le_bytes(bytes.try_into().unwrap()))
|
||||
.unwrap_or(0);
|
||||
let mut on_chain_quantity =
|
||||
self.db.get(&on_chain_key).map_or(0, |bytes| u32::from_le_bytes(bytes.try_into().unwrap()));
|
||||
|
||||
let this_provided_id = on_chain_quantity;
|
||||
txn.put(Self::on_chain_provided_key(&self.genesis, order, this_provided_id), tx);
|
||||
|
|
|
@ -348,7 +348,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Network for TendermintNetwork<D, T, P>
|
|||
if self.blockchain.write().await.add_transaction::<Self>(
|
||||
true,
|
||||
Transaction::Tendermint(tx),
|
||||
self.signature_scheme(),
|
||||
&self.signature_scheme(),
|
||||
) == Ok(true)
|
||||
{
|
||||
self.p2p.broadcast(signer.genesis, to_broadcast).await;
|
||||
|
@ -362,7 +362,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Network for TendermintNetwork<D, T, P>
|
|||
.blockchain
|
||||
.read()
|
||||
.await
|
||||
.verify_block::<Self>(&block, self.signature_scheme(), false)
|
||||
.verify_block::<Self>(&block, &self.signature_scheme(), false)
|
||||
.map_err(|e| match e {
|
||||
BlockError::NonLocalProvided(_) => TendermintBlockError::Temporal,
|
||||
_ => {
|
||||
|
@ -398,7 +398,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Network for TendermintNetwork<D, T, P>
|
|||
let block_res = self.blockchain.write().await.add_block::<Self>(
|
||||
&block,
|
||||
encoded_commit.clone(),
|
||||
self.signature_scheme(),
|
||||
&self.signature_scheme(),
|
||||
);
|
||||
match block_res {
|
||||
Ok(()) => {
|
||||
|
@ -425,7 +425,7 @@ impl<D: Db, T: TransactionTrait, P: P2p> Network for TendermintNetwork<D, T, P>
|
|||
*self.to_rebroadcast.write().await = vec![];
|
||||
|
||||
Some(TendermintBlock(
|
||||
self.blockchain.write().await.build_block::<Self>(self.signature_scheme()).serialize(),
|
||||
self.blockchain.write().await.build_block::<Self>(&self.signature_scheme()).serialize(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ fn decode_and_verify_signed_message<N: Network>(
|
|||
// re-implements an entire foreign library's checks for malicious behavior).
|
||||
pub(crate) fn verify_tendermint_tx<N: Network>(
|
||||
tx: &TendermintTx,
|
||||
schema: N::SignatureScheme,
|
||||
schema: &N::SignatureScheme,
|
||||
commit: impl Fn(u32) -> Option<Commit<N::SignatureScheme>>,
|
||||
) -> Result<(), TransactionError> {
|
||||
tx.verify()?;
|
||||
|
@ -98,8 +98,8 @@ pub(crate) fn verify_tendermint_tx<N: Network>(
|
|||
TendermintTx::SlashEvidence(ev) => {
|
||||
match ev {
|
||||
Evidence::ConflictingMessages(first, second) => {
|
||||
let first = decode_and_verify_signed_message::<N>(first, &schema)?.msg;
|
||||
let second = decode_and_verify_signed_message::<N>(second, &schema)?.msg;
|
||||
let first = decode_and_verify_signed_message::<N>(first, schema)?.msg;
|
||||
let second = decode_and_verify_signed_message::<N>(second, schema)?.msg;
|
||||
|
||||
// Make sure they're distinct messages, from the same sender, within the same block
|
||||
if (first == second) || (first.sender != second.sender) || (first.block != second.block) {
|
||||
|
@ -112,8 +112,8 @@ pub(crate) fn verify_tendermint_tx<N: Network>(
|
|||
}
|
||||
}
|
||||
Evidence::ConflictingPrecommit(first, second) => {
|
||||
let first = decode_and_verify_signed_message::<N>(first, &schema)?.msg;
|
||||
let second = decode_and_verify_signed_message::<N>(second, &schema)?.msg;
|
||||
let first = decode_and_verify_signed_message::<N>(first, schema)?.msg;
|
||||
let second = decode_and_verify_signed_message::<N>(second, schema)?.msg;
|
||||
|
||||
if (first.sender != second.sender) || (first.block != second.block) {
|
||||
Err(TransactionError::InvalidContent)?;
|
||||
|
@ -136,7 +136,7 @@ pub(crate) fn verify_tendermint_tx<N: Network>(
|
|||
Err(TransactionError::InvalidContent)?
|
||||
}
|
||||
Evidence::InvalidPrecommit(msg) => {
|
||||
let msg = decode_and_verify_signed_message::<N>(msg, &schema)?.msg;
|
||||
let msg = decode_and_verify_signed_message::<N>(msg, schema)?.msg;
|
||||
|
||||
let Data::Precommit(Some((id, sig))) = &msg.data else {
|
||||
Err(TransactionError::InvalidContent)?
|
||||
|
@ -173,7 +173,7 @@ pub(crate) fn verify_tendermint_tx<N: Network>(
|
|||
}
|
||||
}
|
||||
Evidence::InvalidValidRound(msg) => {
|
||||
let msg = decode_and_verify_signed_message::<N>(msg, &schema)?.msg;
|
||||
let msg = decode_and_verify_signed_message::<N>(msg, schema)?.msg;
|
||||
|
||||
let Data::Proposal(Some(vr), _) = &msg.data else {
|
||||
Err(TransactionError::InvalidContent)?
|
||||
|
|
|
@ -89,7 +89,7 @@ fn empty_block() {
|
|||
LAST,
|
||||
HashMap::new(),
|
||||
&mut |_, _| None,
|
||||
validators,
|
||||
&validators,
|
||||
commit,
|
||||
unsigned_in_chain,
|
||||
provided_in_chain,
|
||||
|
@ -129,7 +129,7 @@ fn duplicate_nonces() {
|
|||
last_nonce += 1;
|
||||
Some(res)
|
||||
},
|
||||
validators.clone(),
|
||||
&validators,
|
||||
commit,
|
||||
unsigned_in_chain,
|
||||
provided_in_chain,
|
||||
|
|
|
@ -44,12 +44,12 @@ fn block_addition() {
|
|||
let genesis = new_genesis();
|
||||
let validators = Arc::new(Validators::new(genesis, vec![]).unwrap());
|
||||
let (db, mut blockchain) = new_blockchain::<SignedTransaction>(genesis, &[]);
|
||||
let block = blockchain.build_block::<N>(validators.clone());
|
||||
let block = blockchain.build_block::<N>(&validators);
|
||||
|
||||
assert_eq!(block.header.parent, genesis);
|
||||
assert_eq!(block.header.transactions, [0; 32]);
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], validators).is_ok());
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], &validators).is_ok());
|
||||
assert_eq!(blockchain.tip(), block.hash());
|
||||
assert_eq!(blockchain.block_number(), 1);
|
||||
assert_eq!(
|
||||
|
@ -64,21 +64,21 @@ fn invalid_block() {
|
|||
let validators = Arc::new(Validators::new(genesis, vec![]).unwrap());
|
||||
let (_, mut blockchain) = new_blockchain::<SignedTransaction>(genesis, &[]);
|
||||
|
||||
let block = blockchain.build_block::<N>(validators.clone());
|
||||
let block = blockchain.build_block::<N>(&validators);
|
||||
|
||||
// Mutate parent
|
||||
{
|
||||
#[allow(clippy::redundant_clone)] // False positive
|
||||
let mut block = block.clone();
|
||||
block.header.parent = Blake2s256::digest(block.header.parent).into();
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
}
|
||||
|
||||
// Mutate tranactions merkle
|
||||
{
|
||||
let mut block = block;
|
||||
block.header.transactions = Blake2s256::digest(block.header.transactions).into();
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
}
|
||||
|
||||
let key = Zeroizing::new(<Ristretto as Ciphersuite>::F::random(&mut OsRng));
|
||||
|
@ -89,7 +89,7 @@ fn invalid_block() {
|
|||
// Manually create the block to bypass build_block's checks
|
||||
let block = Block::new(blockchain.tip(), vec![], vec![Transaction::Application(tx.clone())]);
|
||||
assert_eq!(block.header.transactions, merkle(&[tx.hash()]));
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
}
|
||||
|
||||
// Run the rest of the tests with them as a participant
|
||||
|
@ -99,22 +99,22 @@ fn invalid_block() {
|
|||
{
|
||||
let block = Block::new(blockchain.tip(), vec![], vec![Transaction::Application(tx.clone())]);
|
||||
assert_eq!(block.header.transactions, merkle(&[tx.hash()]));
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
}
|
||||
|
||||
{
|
||||
// Add a valid transaction
|
||||
let (_, mut blockchain) = new_blockchain(genesis, &[tx.1.signer]);
|
||||
blockchain
|
||||
.add_transaction::<N>(true, Transaction::Application(tx.clone()), validators.clone())
|
||||
.add_transaction::<N>(true, Transaction::Application(tx.clone()), &validators)
|
||||
.unwrap();
|
||||
let mut block = blockchain.build_block::<N>(validators.clone());
|
||||
let mut block = blockchain.build_block::<N>(&validators);
|
||||
assert_eq!(block.header.transactions, merkle(&[tx.hash()]));
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
|
||||
// And verify mutating the transactions merkle now causes a failure
|
||||
block.header.transactions = merkle(&[]);
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -122,24 +122,22 @@ fn invalid_block() {
|
|||
let tx = crate::tests::signed_transaction(&mut OsRng, genesis, &key, 5);
|
||||
// Manually create the block to bypass build_block's checks
|
||||
let block = Block::new(blockchain.tip(), vec![], vec![Transaction::Application(tx)]);
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
}
|
||||
|
||||
{
|
||||
// Invalid signature
|
||||
let (_, mut blockchain) = new_blockchain(genesis, &[tx.1.signer]);
|
||||
blockchain
|
||||
.add_transaction::<N>(true, Transaction::Application(tx), validators.clone())
|
||||
.unwrap();
|
||||
let mut block = blockchain.build_block::<N>(validators.clone());
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
blockchain.add_transaction::<N>(true, Transaction::Application(tx), &validators).unwrap();
|
||||
let mut block = blockchain.build_block::<N>(&validators);
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
match &mut block.transactions[0] {
|
||||
Transaction::Application(tx) => {
|
||||
tx.1.signature.s += <Ristretto as Ciphersuite>::F::ONE;
|
||||
}
|
||||
_ => panic!("non-signed tx found"),
|
||||
}
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
|
||||
// Make sure this isn't because the merkle changed due to the transaction hash including the
|
||||
// signature (which it explicitly isn't allowed to anyways)
|
||||
|
@ -166,12 +164,10 @@ fn signed_transaction() {
|
|||
panic!("tendermint tx found");
|
||||
};
|
||||
let next_nonce = blockchain.next_nonce(&signer, &[]).unwrap();
|
||||
blockchain
|
||||
.add_transaction::<N>(true, Transaction::Application(tx), validators.clone())
|
||||
.unwrap();
|
||||
blockchain.add_transaction::<N>(true, Transaction::Application(tx), &validators).unwrap();
|
||||
assert_eq!(next_nonce + 1, blockchain.next_nonce(&signer, &[]).unwrap());
|
||||
}
|
||||
let block = blockchain.build_block::<N>(validators.clone());
|
||||
let block = blockchain.build_block::<N>(&validators);
|
||||
assert_eq!(block, Block::new(blockchain.tip(), vec![], mempool.clone()));
|
||||
assert_eq!(blockchain.tip(), tip);
|
||||
assert_eq!(block.header.parent, tip);
|
||||
|
@ -185,8 +181,8 @@ fn signed_transaction() {
|
|||
);
|
||||
|
||||
// Verify and add the block
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], validators.clone()).is_ok());
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], &validators).is_ok());
|
||||
assert_eq!(blockchain.tip(), block.hash());
|
||||
};
|
||||
|
||||
|
@ -233,21 +229,21 @@ fn provided_transaction() {
|
|||
{
|
||||
// Non-provided transactions should fail verification because we don't have them locally.
|
||||
let block = Block::new(blockchain.tip(), vec![tx.clone()], vec![]);
|
||||
assert!(blockchain.verify_block::<N>(&block, validators.clone(), false).is_err());
|
||||
assert!(blockchain.verify_block::<N>(&block, &validators, false).is_err());
|
||||
|
||||
// Provided transactions should pass verification
|
||||
blockchain.provide_transaction(tx.clone()).unwrap();
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
|
||||
// add_block should work for verified blocks
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], validators.clone()).is_ok());
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], &validators).is_ok());
|
||||
|
||||
let block = Block::new(blockchain.tip(), vec![tx.clone()], vec![]);
|
||||
|
||||
// The provided transaction should no longer considered provided but added to chain,
|
||||
// causing this error
|
||||
assert_eq!(
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false),
|
||||
blockchain.verify_block::<N>(&block, &validators, false),
|
||||
Err(BlockError::ProvidedAlreadyIncluded)
|
||||
);
|
||||
}
|
||||
|
@ -262,11 +258,11 @@ fn provided_transaction() {
|
|||
// add_block DOES NOT fail for unverified provided transactions if told to add them,
|
||||
// since now we can have them later.
|
||||
let block1 = Block::new(blockchain.tip(), vec![tx1.clone(), tx3.clone()], vec![]);
|
||||
assert!(blockchain.add_block::<N>(&block1, vec![], validators.clone()).is_ok());
|
||||
assert!(blockchain.add_block::<N>(&block1, vec![], &validators).is_ok());
|
||||
|
||||
// in fact, we can have many blocks that have provided txs that we don't have locally.
|
||||
let block2 = Block::new(blockchain.tip(), vec![tx2.clone(), tx4.clone()], vec![]);
|
||||
assert!(blockchain.add_block::<N>(&block2, vec![], validators.clone()).is_ok());
|
||||
assert!(blockchain.add_block::<N>(&block2, vec![], &validators).is_ok());
|
||||
|
||||
// make sure we won't return ok for the block before we actually got the txs
|
||||
let TransactionKind::Provided(order) = tx1.kind() else { panic!("tx wasn't provided") };
|
||||
|
@ -357,11 +353,9 @@ async fn tendermint_evidence_tx() {
|
|||
let Transaction::Tendermint(tx) = tx else {
|
||||
panic!("non-tendermint tx found");
|
||||
};
|
||||
blockchain
|
||||
.add_transaction::<N>(true, Transaction::Tendermint(tx), validators.clone())
|
||||
.unwrap();
|
||||
blockchain.add_transaction::<N>(true, Transaction::Tendermint(tx), &validators).unwrap();
|
||||
}
|
||||
let block = blockchain.build_block::<N>(validators.clone());
|
||||
let block = blockchain.build_block::<N>(&validators);
|
||||
assert_eq!(blockchain.tip(), tip);
|
||||
assert_eq!(block.header.parent, tip);
|
||||
|
||||
|
@ -371,8 +365,8 @@ async fn tendermint_evidence_tx() {
|
|||
}
|
||||
|
||||
// Verify and add the block
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], validators.clone()).is_ok());
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
assert!(blockchain.add_block::<N>(&block, vec![], &validators).is_ok());
|
||||
assert_eq!(blockchain.tip(), block.hash());
|
||||
};
|
||||
|
||||
|
@ -467,7 +461,7 @@ async fn block_tx_ordering() {
|
|||
let signed_tx = Transaction::Application(SignedTx::Signed(Box::new(
|
||||
crate::tests::signed_transaction(&mut OsRng, genesis, &key, i),
|
||||
)));
|
||||
blockchain.add_transaction::<N>(true, signed_tx.clone(), validators.clone()).unwrap();
|
||||
blockchain.add_transaction::<N>(true, signed_tx.clone(), &validators).unwrap();
|
||||
mempool.push(signed_tx);
|
||||
|
||||
let unsigned_tx = Transaction::Tendermint(
|
||||
|
@ -477,7 +471,7 @@ async fn block_tx_ordering() {
|
|||
)
|
||||
.await,
|
||||
);
|
||||
blockchain.add_transaction::<N>(true, unsigned_tx.clone(), validators.clone()).unwrap();
|
||||
blockchain.add_transaction::<N>(true, unsigned_tx.clone(), &validators).unwrap();
|
||||
mempool.push(unsigned_tx);
|
||||
|
||||
let provided_tx =
|
||||
|
@ -485,7 +479,7 @@ async fn block_tx_ordering() {
|
|||
blockchain.provide_transaction(provided_tx.clone()).unwrap();
|
||||
provided_txs.push(provided_tx);
|
||||
}
|
||||
let block = blockchain.build_block::<N>(validators.clone());
|
||||
let block = blockchain.build_block::<N>(&validators);
|
||||
|
||||
assert_eq!(blockchain.tip(), tip);
|
||||
assert_eq!(block.header.parent, tip);
|
||||
|
@ -509,7 +503,7 @@ async fn block_tx_ordering() {
|
|||
}
|
||||
|
||||
// should be a valid block
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap();
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap();
|
||||
|
||||
// Unsigned before Provided
|
||||
{
|
||||
|
@ -518,7 +512,7 @@ async fn block_tx_ordering() {
|
|||
let unsigned = block.transactions.remove(128);
|
||||
block.transactions.insert(0, unsigned);
|
||||
assert_eq!(
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap_err(),
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap_err(),
|
||||
BlockError::WrongTransactionOrder
|
||||
);
|
||||
}
|
||||
|
@ -529,7 +523,7 @@ async fn block_tx_ordering() {
|
|||
let signed = block.transactions.remove(256);
|
||||
block.transactions.insert(0, signed);
|
||||
assert_eq!(
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap_err(),
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap_err(),
|
||||
BlockError::WrongTransactionOrder
|
||||
);
|
||||
}
|
||||
|
@ -539,7 +533,7 @@ async fn block_tx_ordering() {
|
|||
let mut block = block;
|
||||
block.transactions.swap(128, 256);
|
||||
assert_eq!(
|
||||
blockchain.verify_block::<N>(&block, validators.clone(), false).unwrap_err(),
|
||||
blockchain.verify_block::<N>(&block, &validators, false).unwrap_err(),
|
||||
BlockError::WrongTransactionOrder
|
||||
);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ async fn mempool_addition() {
|
|||
&|_, _| Some(0),
|
||||
true,
|
||||
Transaction::Application(first_tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
)
|
||||
|
@ -63,7 +63,7 @@ async fn mempool_addition() {
|
|||
&|_, _| None,
|
||||
true,
|
||||
Transaction::Tendermint(evidence_tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
)
|
||||
|
@ -78,7 +78,7 @@ async fn mempool_addition() {
|
|||
&|_, _| Some(0),
|
||||
true,
|
||||
Transaction::Application(first_tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
),
|
||||
|
@ -89,7 +89,7 @@ async fn mempool_addition() {
|
|||
&|_, _| None,
|
||||
true,
|
||||
Transaction::Tendermint(evidence_tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
),
|
||||
|
@ -103,7 +103,7 @@ async fn mempool_addition() {
|
|||
&|_, _| Some(0),
|
||||
true,
|
||||
Transaction::Application(second_tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
),
|
||||
|
@ -115,7 +115,7 @@ async fn mempool_addition() {
|
|||
&|_, _| Some(0),
|
||||
true,
|
||||
Transaction::Application(second_tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
),
|
||||
|
@ -133,7 +133,7 @@ async fn mempool_addition() {
|
|||
&|_, _| Some(2),
|
||||
true,
|
||||
Transaction::Application(tx.clone()),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit
|
||||
)
|
||||
|
@ -173,7 +173,7 @@ fn too_many_mempool() {
|
|||
&|_, _| Some(0),
|
||||
false,
|
||||
Transaction::Application(signed_transaction(&mut OsRng, genesis, &key, i)),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
)
|
||||
|
@ -190,7 +190,7 @@ fn too_many_mempool() {
|
|||
&key,
|
||||
ACCOUNT_MEMPOOL_LIMIT
|
||||
)),
|
||||
validators.clone(),
|
||||
&validators,
|
||||
unsigned_in_chain,
|
||||
commit,
|
||||
),
|
||||
|
|
|
@ -57,13 +57,13 @@ async fn invalid_valid_round() {
|
|||
|
||||
// This should be invalid evidence if a valid valid round is specified
|
||||
let (_, tx) = valid_round_tx(None).await;
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
|
||||
// If an invalid valid round is specified (>= current), this should be invalid evidence
|
||||
let (mut signed, tx) = valid_round_tx(Some(RoundNumber(0))).await;
|
||||
|
||||
// should pass
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap();
|
||||
|
||||
// change the signature
|
||||
let mut random_sig = [0u8; 64];
|
||||
|
@ -72,7 +72,7 @@ async fn invalid_valid_round() {
|
|||
let tx = TendermintTx::SlashEvidence(Evidence::InvalidValidRound(signed.encode()));
|
||||
|
||||
// should fail
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators, commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
@ -94,7 +94,7 @@ async fn invalid_precommit_signature() {
|
|||
};
|
||||
|
||||
// Empty Precommit should fail.
|
||||
assert!(verify_tendermint_tx::<N>(&precommit(None).await.1, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&precommit(None).await.1, &validators, commit).is_err());
|
||||
|
||||
// valid precommit signature should fail.
|
||||
let block_id = [0x22u8; 32];
|
||||
|
@ -105,7 +105,7 @@ async fn invalid_precommit_signature() {
|
|||
|
||||
assert!(verify_tendermint_tx::<N>(
|
||||
&precommit(Some((block_id, signer.clone().sign(&commit_msg).await))).await.1,
|
||||
validators.clone(),
|
||||
&validators,
|
||||
commit
|
||||
)
|
||||
.is_err());
|
||||
|
@ -113,14 +113,14 @@ async fn invalid_precommit_signature() {
|
|||
// any other signature can be used as evidence.
|
||||
{
|
||||
let (mut signed, tx) = precommit(Some((block_id, signer.sign(&[]).await))).await;
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap();
|
||||
|
||||
// So long as we can authenticate where it came from
|
||||
let mut random_sig = [0u8; 64];
|
||||
OsRng.fill_bytes(&mut random_sig);
|
||||
signed.sig = random_sig;
|
||||
let tx = TendermintTx::SlashEvidence(Evidence::InvalidPrecommit(signed.encode()));
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators, commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,10 +170,10 @@ async fn evidence_with_prevote() {
|
|||
|
||||
// No prevote message alone should be valid as slash evidence at this time
|
||||
for prevote in prevote(None).await {
|
||||
assert!(verify_tendermint_tx::<N>(&prevote, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&prevote, &validators, commit).is_err());
|
||||
}
|
||||
for prevote in prevote(Some([0x22u8; 32])).await {
|
||||
assert!(verify_tendermint_tx::<N>(&prevote, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&prevote, &validators, commit).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_1.encode(),
|
||||
));
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
|
||||
// conflicting data should pass
|
||||
let signed_2 = signed_for_b_r(0, 0, Data::Proposal(None, TendermintBlock(vec![0x22]))).await;
|
||||
|
@ -207,7 +207,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap();
|
||||
|
||||
// Except if it has a distinct round number, as we don't check cross-round conflicts
|
||||
// (except for Precommit)
|
||||
|
@ -216,7 +216,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap_err();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap_err();
|
||||
|
||||
// Proposals for different block numbers should also fail as evidence
|
||||
let signed_2 = signed_for_b_r(1, 0, Data::Proposal(None, TendermintBlock(vec![0x22]))).await;
|
||||
|
@ -224,7 +224,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap_err();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap_err();
|
||||
}
|
||||
|
||||
// Prevote
|
||||
|
@ -235,7 +235,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_1.encode(),
|
||||
));
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
|
||||
// conflicting data should pass
|
||||
let signed_2 = signed_for_b_r(0, 0, Data::Prevote(Some([0x22; 32]))).await;
|
||||
|
@ -243,7 +243,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap();
|
||||
|
||||
// Except if it has a distinct round number, as we don't check cross-round conflicts
|
||||
// (except for Precommit)
|
||||
|
@ -252,7 +252,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap_err();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap_err();
|
||||
|
||||
// Proposals for different block numbers should also fail as evidence
|
||||
let signed_2 = signed_for_b_r(1, 0, Data::Prevote(Some([0x22; 32]))).await;
|
||||
|
@ -260,7 +260,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap_err();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap_err();
|
||||
}
|
||||
|
||||
// Precommit
|
||||
|
@ -272,7 +272,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_1.encode(),
|
||||
));
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
|
||||
// For precommit, the round number is ignored
|
||||
let signed_2 = signed_for_b_r(0, 1, Data::Precommit(Some(([0x22; 32], sig)))).await;
|
||||
|
@ -280,7 +280,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
verify_tendermint_tx::<N>(&tx, validators.clone(), commit).unwrap();
|
||||
verify_tendermint_tx::<N>(&tx, &validators, commit).unwrap();
|
||||
|
||||
// Yet the block number isn't
|
||||
let signed_2 = signed_for_b_r(1, 0, Data::Precommit(Some(([0x22; 32], sig)))).await;
|
||||
|
@ -288,7 +288,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
}
|
||||
|
||||
// msgs from different senders should fail
|
||||
|
@ -320,7 +320,7 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
let validators =
|
||||
Arc::new(Validators::new(genesis, vec![(signer_pub, 1), (signer_pub_2, 1)]).unwrap());
|
||||
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators, commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
}
|
||||
|
||||
// msgs with different steps should fail
|
||||
|
@ -331,6 +331,6 @@ async fn conflicting_msgs_evidence_tx() {
|
|||
signed_1.encode(),
|
||||
signed_2.encode(),
|
||||
));
|
||||
assert!(verify_tendermint_tx::<N>(&tx, validators.clone(), commit).is_err());
|
||||
assert!(verify_tendermint_tx::<N>(&tx, &validators, commit).is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -191,8 +191,7 @@ pub(crate) fn verify_transaction<F: GAIN, T: Transaction>(
|
|||
tx.verify()?;
|
||||
|
||||
match tx.kind() {
|
||||
TransactionKind::Provided(_) => {}
|
||||
TransactionKind::Unsigned => {}
|
||||
TransactionKind::Provided(_) | TransactionKind::Unsigned => {}
|
||||
TransactionKind::Signed(order, Signed { signer, nonce, signature }) => {
|
||||
if let Some(next_nonce) = get_and_increment_nonce(signer, &order) {
|
||||
if *nonce != next_nonce {
|
||||
|
|
|
@ -543,8 +543,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
|
||||
self.slash(sender, slash).await
|
||||
}
|
||||
Err(TendermintError::Temporal) => (),
|
||||
Err(TendermintError::AlreadyHandled) => (),
|
||||
Err(TendermintError::Temporal | TendermintError::AlreadyHandled) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -627,7 +626,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
// Uses a junk signature since message equality disregards the signature
|
||||
if self.block.log.has_consensus(
|
||||
msg.round,
|
||||
Data::Precommit(Some((block.id(), self.signer.sign(&[]).await))),
|
||||
&Data::Precommit(Some((block.id(), self.signer.sign(&[]).await))),
|
||||
) {
|
||||
// If msg.round is in the future, these Precommits won't have their inner signatures
|
||||
// verified
|
||||
|
@ -714,7 +713,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
// of the round map
|
||||
if (self.block.round().step == Step::Prevote) && matches!(msg.data, Data::Prevote(_)) {
|
||||
let (participation, weight) =
|
||||
self.block.log.message_instances(self.block.round().number, Data::Prevote(None));
|
||||
self.block.log.message_instances(self.block.round().number, &Data::Prevote(None));
|
||||
// 34-35
|
||||
if participation >= self.weights.threshold() {
|
||||
self.block.round_mut().set_timeout(Step::Prevote);
|
||||
|
@ -767,7 +766,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
// 23 and 29. If it's some, both are satisfied if they're for the same ID. If it's some
|
||||
// with different IDs, the function on 22 rejects yet the function on 28 has one other
|
||||
// condition
|
||||
let locked = self.block.locked.as_ref().map(|(_, id)| id == &block.id()).unwrap_or(true);
|
||||
let locked = self.block.locked.as_ref().map_or(true, |(_, id)| id == &block.id());
|
||||
let mut vote = raw_vote.filter(|_| locked);
|
||||
|
||||
if let Some(vr) = vr {
|
||||
|
@ -780,7 +779,7 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
))?;
|
||||
}
|
||||
|
||||
if self.block.log.has_consensus(*vr, Data::Prevote(Some(block.id()))) {
|
||||
if self.block.log.has_consensus(*vr, &Data::Prevote(Some(block.id()))) {
|
||||
// Allow differing locked values if the proposal has a newer valid round
|
||||
// This is the other condition described above
|
||||
if let Some((locked_round, _)) = self.block.locked.as_ref() {
|
||||
|
@ -798,25 +797,18 @@ impl<N: Network + 'static> TendermintMachine<N> {
|
|||
return Ok(None);
|
||||
}
|
||||
|
||||
if self
|
||||
.block
|
||||
.valid
|
||||
.as_ref()
|
||||
.map(|(round, _)| round != &self.block.round().number)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if self.block.valid.as_ref().map_or(true, |(round, _)| round != &self.block.round().number) {
|
||||
// 36-43
|
||||
|
||||
// The run once condition is implemented above. Since valid will always be set by this, it
|
||||
// not being set, or only being set historically, means this has yet to be run
|
||||
|
||||
if self.block.log.has_consensus(self.block.round().number, Data::Prevote(Some(block.id()))) {
|
||||
if self.block.log.has_consensus(self.block.round().number, &Data::Prevote(Some(block.id()))) {
|
||||
match self.network.validate(block).await {
|
||||
Ok(()) => (),
|
||||
// BlockError::Temporal is due to a temporal error we have, yet a supermajority of the
|
||||
// network does not, Because we do not believe this block to be fatally invalid, and
|
||||
// because a supermajority deems it valid, accept it.
|
||||
Err(BlockError::Temporal) => (),
|
||||
Ok(()) | Err(BlockError::Temporal) => (),
|
||||
Err(BlockError::Fatal) => {
|
||||
log::warn!(target: "tendermint", "Validator proposed a fatally invalid block");
|
||||
// TODO: Produce evidence of this for the higher level code to decide what to do with
|
||||
|
|
|
@ -64,14 +64,14 @@ impl<N: Network> MessageLog<N> {
|
|||
|
||||
// For a given round, return the participating weight for this step, and the weight agreeing with
|
||||
// the data.
|
||||
pub(crate) fn message_instances(&self, round: RoundNumber, data: DataFor<N>) -> (u64, u64) {
|
||||
pub(crate) fn message_instances(&self, round: RoundNumber, data: &DataFor<N>) -> (u64, u64) {
|
||||
let mut participating = 0;
|
||||
let mut weight = 0;
|
||||
for (participant, msgs) in &self.log[&round] {
|
||||
if let Some(msg) = msgs.get(&data.step()) {
|
||||
let validator_weight = self.weights.weight(*participant);
|
||||
participating += validator_weight;
|
||||
if data == msg.msg.data {
|
||||
if data == &msg.msg.data {
|
||||
weight += validator_weight;
|
||||
}
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ impl<N: Network> MessageLog<N> {
|
|||
}
|
||||
|
||||
// Check if consensus has been reached on a specific piece of data
|
||||
pub(crate) fn has_consensus(&self, round: RoundNumber, data: DataFor<N>) -> bool {
|
||||
pub(crate) fn has_consensus(&self, round: RoundNumber, data: &DataFor<N>) -> bool {
|
||||
let (_, weight) = self.message_instances(round, data);
|
||||
weight >= self.weights.threshold()
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ pub trait CiphersuitePromote<C2: Ciphersuite> {
|
|||
fn promote(self) -> ThresholdKeys<C2>;
|
||||
}
|
||||
|
||||
fn transcript<G: GroupEncoding>(key: G, i: Participant) -> RecommendedTranscript {
|
||||
fn transcript<G: GroupEncoding>(key: &G, i: Participant) -> RecommendedTranscript {
|
||||
let mut transcript = RecommendedTranscript::new(b"DKG Generator Promotion v0.2");
|
||||
transcript.append_message(b"group_key", key.to_bytes());
|
||||
transcript.append_message(b"participant", i.to_bytes());
|
||||
|
@ -79,7 +79,7 @@ where
|
|||
share: C2::generator() * base.secret_share().deref(),
|
||||
proof: DLEqProof::prove(
|
||||
rng,
|
||||
&mut transcript(base.core.group_key(), base.params().i),
|
||||
&mut transcript(&base.core.group_key(), base.params().i),
|
||||
&[C1::generator(), C2::generator()],
|
||||
base.secret_share(),
|
||||
),
|
||||
|
@ -105,7 +105,7 @@ where
|
|||
proof
|
||||
.proof
|
||||
.verify(
|
||||
&mut transcript(self.base.core.group_key(), i),
|
||||
&mut transcript(&self.base.core.group_key(), i),
|
||||
&[C1::generator(), C2::generator()],
|
||||
&[original_shares[&i], proof.share],
|
||||
)
|
||||
|
|
|
@ -135,10 +135,10 @@ mod literal {
|
|||
const TWO: Participant = Participant(2);
|
||||
|
||||
fn test_blame(
|
||||
commitment_msgs: HashMap<Participant, EncryptionKeyMessage<Ristretto, Commitments<Ristretto>>>,
|
||||
commitment_msgs: &HashMap<Participant, EncryptionKeyMessage<Ristretto, Commitments<Ristretto>>>,
|
||||
machines: Vec<BlameMachine<Ristretto>>,
|
||||
msg: FrostEncryptedMessage<Ristretto>,
|
||||
blame: Option<EncryptionKeyProof<Ristretto>>,
|
||||
msg: &FrostEncryptedMessage<Ristretto>,
|
||||
blame: &Option<EncryptionKeyProof<Ristretto>>,
|
||||
) {
|
||||
for machine in machines {
|
||||
let (additional, blamed) = machine.blame(ONE, TWO, msg.clone(), blame.clone());
|
||||
|
@ -188,7 +188,7 @@ mod literal {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
test_blame(commitment_msgs, machines, secret_shares[&ONE][&TWO].clone(), blame.unwrap());
|
||||
test_blame(&commitment_msgs, machines, &secret_shares[&ONE][&TWO].clone(), &blame.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -228,7 +228,7 @@ mod literal {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
blame.as_mut().unwrap().as_mut().unwrap().invalidate_key();
|
||||
test_blame(commitment_msgs, machines, secret_shares[&TWO][&ONE].clone(), blame.unwrap());
|
||||
test_blame(&commitment_msgs, machines, &secret_shares[&TWO][&ONE].clone(), &blame.unwrap());
|
||||
}
|
||||
|
||||
// This should be largely equivalent to the prior test
|
||||
|
@ -263,7 +263,7 @@ mod literal {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
blame.as_mut().unwrap().as_mut().unwrap().invalidate_dleq();
|
||||
test_blame(commitment_msgs, machines, secret_shares[&TWO][&ONE].clone(), blame.unwrap());
|
||||
test_blame(&commitment_msgs, machines, &secret_shares[&TWO][&ONE].clone(), &blame.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -296,7 +296,7 @@ mod literal {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
test_blame(commitment_msgs, machines, secret_shares[&ONE][&TWO].clone(), blame.unwrap());
|
||||
test_blame(&commitment_msgs, machines, &secret_shares[&ONE][&TWO].clone(), &blame.unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -329,6 +329,6 @@ mod literal {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
test_blame(commitment_msgs, machines, secret_shares[&ONE][&TWO].clone(), blame.unwrap());
|
||||
test_blame(&commitment_msgs, machines, &secret_shares[&ONE][&TWO].clone(), &blame.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ where
|
|||
#[allow(non_snake_case)]
|
||||
pub(crate) fn prove<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
||||
rng: &mut R,
|
||||
transcript: T,
|
||||
transcript: &T,
|
||||
generators: (Generators<G0>, Generators<G1>),
|
||||
ring: &[(G0, G1)],
|
||||
mut actual: usize,
|
||||
|
@ -122,7 +122,7 @@ where
|
|||
#[allow(non_snake_case)]
|
||||
let mut R = original_R;
|
||||
|
||||
for i in ((actual + 1) .. (actual + RING_LEN + 1)).map(|i| i % RING_LEN) {
|
||||
for i in ((actual + 1) ..= (actual + RING_LEN)).map(|i| i % RING_LEN) {
|
||||
let e = Self::nonces(transcript.clone(), R);
|
||||
if i == 0 {
|
||||
match Re_0 {
|
||||
|
@ -144,11 +144,10 @@ where
|
|||
r.0.zeroize();
|
||||
r.1.zeroize();
|
||||
break;
|
||||
// Generate a decoy response
|
||||
} else {
|
||||
s[i] = (G0::Scalar::random(&mut *rng), G1::Scalar::random(&mut *rng));
|
||||
}
|
||||
|
||||
// Generate a decoy response
|
||||
s[i] = (G0::Scalar::random(&mut *rng), G1::Scalar::random(&mut *rng));
|
||||
R = Self::R(generators, s[i], ring[i], e);
|
||||
}
|
||||
|
||||
|
@ -159,7 +158,7 @@ where
|
|||
pub(crate) fn verify<R: RngCore + CryptoRng, T: Clone + Transcript>(
|
||||
&self,
|
||||
rng: &mut R,
|
||||
transcript: T,
|
||||
transcript: &T,
|
||||
generators: (Generators<G0>, Generators<G1>),
|
||||
batch: &mut (BatchVerifier<(), G0>, BatchVerifier<(), G1>),
|
||||
ring: &[(G0, G1)],
|
||||
|
|
|
@ -47,10 +47,8 @@ impl BitSignature {
|
|||
|
||||
pub(crate) const fn bits(&self) -> u8 {
|
||||
match self {
|
||||
BitSignature::ClassicLinear => 1,
|
||||
BitSignature::ConciseLinear => 2,
|
||||
BitSignature::EfficientLinear => 1,
|
||||
BitSignature::CompromiseLinear => 2,
|
||||
BitSignature::ClassicLinear | BitSignature::EfficientLinear => 1,
|
||||
BitSignature::ConciseLinear | BitSignature::CompromiseLinear => 2,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,10 +58,8 @@ impl BitSignature {
|
|||
|
||||
fn aos_form<G0: PrimeGroup, G1: PrimeGroup>(&self) -> Re<G0, G1> {
|
||||
match self {
|
||||
BitSignature::ClassicLinear => Re::e_default(),
|
||||
BitSignature::ConciseLinear => Re::e_default(),
|
||||
BitSignature::EfficientLinear => Re::R_default(),
|
||||
BitSignature::CompromiseLinear => Re::R_default(),
|
||||
BitSignature::ClassicLinear | BitSignature::ConciseLinear => Re::e_default(),
|
||||
BitSignature::EfficientLinear | BitSignature::CompromiseLinear => Re::R_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +125,7 @@ where
|
|||
|
||||
let signature = Aos::prove(
|
||||
rng,
|
||||
transcript.clone(),
|
||||
transcript,
|
||||
generators,
|
||||
&Self::ring(*pow_2, commitments),
|
||||
usize::from(bits),
|
||||
|
@ -155,7 +151,7 @@ where
|
|||
|
||||
self.signature.verify(
|
||||
rng,
|
||||
transcript.clone(),
|
||||
transcript,
|
||||
generators,
|
||||
batch,
|
||||
&Self::ring(*pow_2, self.commitments),
|
||||
|
|
|
@ -408,10 +408,8 @@ where
|
|||
Self::transcript(transcript, generators, keys);
|
||||
|
||||
let batch_capacity = match BitSignature::from(SIGNATURE) {
|
||||
BitSignature::ClassicLinear => 3,
|
||||
BitSignature::ConciseLinear => 3,
|
||||
BitSignature::EfficientLinear => (self.bits.len() + 1) * 3,
|
||||
BitSignature::CompromiseLinear => (self.bits.len() + 1) * 3,
|
||||
BitSignature::ClassicLinear | BitSignature::ConciseLinear => 3,
|
||||
BitSignature::EfficientLinear | BitSignature::CompromiseLinear => (self.bits.len() + 1) * 3,
|
||||
};
|
||||
let mut batch = (BatchVerifier::new(batch_capacity), BatchVerifier::new(batch_capacity));
|
||||
|
||||
|
|
|
@ -11,14 +11,14 @@ use crate::{
|
|||
|
||||
#[allow(non_snake_case)]
|
||||
#[cfg(feature = "serialize")]
|
||||
fn test_aos_serialization<const RING_LEN: usize>(proof: Aos<G0, G1, RING_LEN>, Re_0: Re<G0, G1>) {
|
||||
fn test_aos_serialization<const RING_LEN: usize>(proof: &Aos<G0, G1, RING_LEN>, Re_0: Re<G0, G1>) {
|
||||
let mut buf = vec![];
|
||||
proof.write(&mut buf).unwrap();
|
||||
let deserialized = Aos::read::<&[u8]>(&mut buf.as_ref(), Re_0).unwrap();
|
||||
assert_eq!(proof, deserialized);
|
||||
assert_eq!(proof, &deserialized);
|
||||
}
|
||||
|
||||
fn test_aos<const RING_LEN: usize>(default: Re<G0, G1>) {
|
||||
fn test_aos<const RING_LEN: usize>(default: &Re<G0, G1>) {
|
||||
let generators = generators();
|
||||
|
||||
let mut ring_keys = [(<G0 as Group>::Scalar::ZERO, <G1 as Group>::Scalar::ZERO); RING_LEN];
|
||||
|
@ -34,7 +34,7 @@ fn test_aos<const RING_LEN: usize>(default: Re<G0, G1>) {
|
|||
for (actual, key) in ring_keys.iter_mut().enumerate() {
|
||||
let proof = Aos::<_, _, RING_LEN>::prove(
|
||||
&mut OsRng,
|
||||
transcript(),
|
||||
&transcript(),
|
||||
generators,
|
||||
&ring,
|
||||
actual,
|
||||
|
@ -43,25 +43,25 @@ fn test_aos<const RING_LEN: usize>(default: Re<G0, G1>) {
|
|||
);
|
||||
|
||||
let mut batch = (BatchVerifier::new(0), BatchVerifier::new(0));
|
||||
proof.verify(&mut OsRng, transcript(), generators, &mut batch, &ring).unwrap();
|
||||
proof.verify(&mut OsRng, &transcript(), generators, &mut batch, &ring).unwrap();
|
||||
// For e, these should have nothing. For R, these should have 6 elements each which sum to 0
|
||||
assert!(batch.0.verify_vartime());
|
||||
assert!(batch.1.verify_vartime());
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
test_aos_serialization(proof, default.clone());
|
||||
test_aos_serialization(&proof, default.clone());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_aos_e() {
|
||||
test_aos::<2>(Re::e_default());
|
||||
test_aos::<4>(Re::e_default());
|
||||
test_aos::<2>(&Re::e_default());
|
||||
test_aos::<4>(&Re::e_default());
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[test]
|
||||
fn test_aos_R() {
|
||||
// Batch verification appreciates the longer vectors, which means not batching bits
|
||||
test_aos::<2>(Re::R_default());
|
||||
test_aos::<2>(&Re::R_default());
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ fn test_multi_dleq() {
|
|||
// 0: 0
|
||||
// 1: 1, 2
|
||||
// 2: 2, 3, 4
|
||||
let key_generators = generators[i .. (i + i + 1)].to_vec();
|
||||
let key_generators = generators[i ..= (i + i)].to_vec();
|
||||
let mut these_pub_keys = vec![];
|
||||
for generator in &key_generators {
|
||||
these_pub_keys.push(generator * key.deref());
|
||||
|
|
|
@ -130,8 +130,8 @@ pub fn test_sqrt<F: Field>() {
|
|||
assert_eq!(root * root, has_root, "sqrt(x)^2 != x");
|
||||
|
||||
let check = |value: (_, _), expected: (_, F), msg| {
|
||||
assert_eq!(bool::from(value.0), bool::from(expected.0), "{}", msg);
|
||||
assert!((value.1 == expected.1) || (value.1 == -expected.1), "{}", msg);
|
||||
assert_eq!(bool::from(value.0), bool::from(expected.0), "{msg}");
|
||||
assert!((value.1 == expected.1) || (value.1 == -expected.1), "{msg}");
|
||||
};
|
||||
check(
|
||||
F::sqrt_ratio(&has_root, &F::ONE),
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
fn ristretto_vectors() {
|
||||
test_with_vectors::<_, curve::Ristretto, curve::IetfRistrettoHram>(
|
||||
&mut OsRng,
|
||||
Vectors::from(
|
||||
&Vectors::from(
|
||||
serde_json::from_str::<serde_json::Value>(include_str!(
|
||||
"vectors/frost-ristretto255-sha512.json"
|
||||
))
|
||||
|
@ -24,7 +24,7 @@ fn ristretto_vectors() {
|
|||
fn ed25519_vectors() {
|
||||
test_with_vectors::<_, curve::Ed25519, curve::IetfEd25519Hram>(
|
||||
&mut OsRng,
|
||||
Vectors::from(
|
||||
&Vectors::from(
|
||||
serde_json::from_str::<serde_json::Value>(include_str!("vectors/frost-ed25519-sha512.json"))
|
||||
.unwrap(),
|
||||
),
|
||||
|
|
|
@ -57,7 +57,7 @@ fn ed448_8032_vector() {
|
|||
fn ed448_vectors() {
|
||||
test_with_vectors::<_, Ed448, IetfEd448Hram>(
|
||||
&mut OsRng,
|
||||
Vectors::from(
|
||||
&Vectors::from(
|
||||
serde_json::from_str::<serde_json::Value>(include_str!("vectors/frost-ed448-shake256.json"))
|
||||
.unwrap(),
|
||||
),
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::curve::{P256, IetfP256Hram};
|
|||
fn secp256k1_vectors() {
|
||||
test_with_vectors::<_, Secp256k1, IetfSecp256k1Hram>(
|
||||
&mut OsRng,
|
||||
Vectors::from(
|
||||
&Vectors::from(
|
||||
serde_json::from_str::<serde_json::Value>(include_str!(
|
||||
"vectors/frost-secp256k1-sha256.json"
|
||||
))
|
||||
|
@ -27,7 +27,7 @@ fn secp256k1_vectors() {
|
|||
fn p256_vectors() {
|
||||
test_with_vectors::<_, P256, IetfP256Hram>(
|
||||
&mut OsRng,
|
||||
Vectors::from(
|
||||
&Vectors::from(
|
||||
serde_json::from_str::<serde_json::Value>(include_str!("vectors/frost-p256-sha256.json"))
|
||||
.unwrap(),
|
||||
),
|
||||
|
|
|
@ -39,7 +39,7 @@ pub fn clone_without<K: Clone + core::cmp::Eq + core::hash::Hash, V: Clone>(
|
|||
/// Spawn algorithm machines for a random selection of signers, each executing the given algorithm.
|
||||
pub fn algorithm_machines<R: RngCore, C: Curve, A: Algorithm<C>>(
|
||||
rng: &mut R,
|
||||
algorithm: A,
|
||||
algorithm: &A,
|
||||
keys: &HashMap<Participant, ThresholdKeys<C>>,
|
||||
) -> HashMap<Participant, AlgorithmMachine<C, A>> {
|
||||
let mut included = vec![];
|
||||
|
@ -167,7 +167,7 @@ pub fn sign_without_caching<R: RngCore + CryptoRng, M: PreprocessMachine>(
|
|||
/// successfully.
|
||||
pub fn sign<R: RngCore + CryptoRng, M: PreprocessMachine>(
|
||||
rng: &mut R,
|
||||
params: <M::SignMachine as SignMachine<M::Signature>>::Params,
|
||||
params: &<M::SignMachine as SignMachine<M::Signature>>::Params,
|
||||
mut keys: HashMap<Participant, <M::SignMachine as SignMachine<M::Signature>>::Keys>,
|
||||
machines: HashMap<Participant, M>,
|
||||
msg: &[u8],
|
||||
|
@ -195,12 +195,12 @@ pub fn sign<R: RngCore + CryptoRng, M: PreprocessMachine>(
|
|||
/// Test a basic Schnorr signature with the provided keys.
|
||||
pub fn test_schnorr_with_keys<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
|
||||
rng: &mut R,
|
||||
keys: HashMap<Participant, ThresholdKeys<C>>,
|
||||
keys: &HashMap<Participant, ThresholdKeys<C>>,
|
||||
) {
|
||||
const MSG: &[u8] = b"Hello, World!";
|
||||
|
||||
let machines = algorithm_machines(&mut *rng, IetfSchnorr::<C, H>::ietf(), &keys);
|
||||
let sig = sign(&mut *rng, IetfSchnorr::<C, H>::ietf(), keys.clone(), machines, MSG);
|
||||
let machines = algorithm_machines(&mut *rng, &IetfSchnorr::<C, H>::ietf(), keys);
|
||||
let sig = sign(&mut *rng, &IetfSchnorr::<C, H>::ietf(), keys.clone(), machines, MSG);
|
||||
let group_key = keys[&Participant::new(1).unwrap()].group_key();
|
||||
assert!(sig.verify(group_key, H::hram(&sig.R, &group_key, MSG)));
|
||||
}
|
||||
|
@ -208,13 +208,13 @@ pub fn test_schnorr_with_keys<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
|
|||
/// Test a basic Schnorr signature.
|
||||
pub fn test_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
|
||||
let keys = key_gen(&mut *rng);
|
||||
test_schnorr_with_keys::<_, _, H>(&mut *rng, keys)
|
||||
test_schnorr_with_keys::<_, _, H>(&mut *rng, &keys)
|
||||
}
|
||||
|
||||
/// Test a basic Schnorr signature, yet with MuSig.
|
||||
pub fn test_musig_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mut R) {
|
||||
let keys = musig_key_gen(&mut *rng);
|
||||
test_schnorr_with_keys::<_, _, H>(&mut *rng, keys)
|
||||
test_schnorr_with_keys::<_, _, H>(&mut *rng, &keys)
|
||||
}
|
||||
|
||||
/// Test an offset Schnorr signature.
|
||||
|
@ -231,8 +231,8 @@ pub fn test_offset_schnorr<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &m
|
|||
assert_eq!(keys.group_key(), offset_key);
|
||||
}
|
||||
|
||||
let machines = algorithm_machines(&mut *rng, IetfSchnorr::<C, H>::ietf(), &keys);
|
||||
let sig = sign(&mut *rng, IetfSchnorr::<C, H>::ietf(), keys.clone(), machines, MSG);
|
||||
let machines = algorithm_machines(&mut *rng, &IetfSchnorr::<C, H>::ietf(), &keys);
|
||||
let sig = sign(&mut *rng, &IetfSchnorr::<C, H>::ietf(), keys.clone(), machines, MSG);
|
||||
let group_key = keys[&Participant::new(1).unwrap()].group_key();
|
||||
assert!(sig.verify(offset_key, H::hram(&sig.R, &group_key, MSG)));
|
||||
}
|
||||
|
@ -242,7 +242,7 @@ pub fn test_schnorr_blame<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(rng: &mu
|
|||
const MSG: &[u8] = b"Hello, World!";
|
||||
|
||||
let keys = key_gen(&mut *rng);
|
||||
let machines = algorithm_machines(&mut *rng, IetfSchnorr::<C, H>::ietf(), &keys);
|
||||
let machines = algorithm_machines(&mut *rng, &IetfSchnorr::<C, H>::ietf(), &keys);
|
||||
|
||||
let (mut machines, shares) = preprocess_and_shares(&mut *rng, machines, |_, _| {}, MSG);
|
||||
|
||||
|
|
|
@ -154,14 +154,14 @@ impl<C: Curve> Algorithm<C> for MultiNonce<C> {
|
|||
// 3) Provide algorithms with nonces which match the group nonces
|
||||
pub fn test_multi_nonce<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let keys = key_gen::<R, C>(&mut *rng);
|
||||
let machines = algorithm_machines(&mut *rng, MultiNonce::<C>::new(), &keys);
|
||||
sign(&mut *rng, MultiNonce::<C>::new(), keys.clone(), machines, &[]);
|
||||
let machines = algorithm_machines(&mut *rng, &MultiNonce::<C>::new(), &keys);
|
||||
sign(&mut *rng, &MultiNonce::<C>::new(), keys.clone(), machines, &[]);
|
||||
}
|
||||
|
||||
/// Test malleating a commitment for a nonce across generators causes the preprocess to error.
|
||||
pub fn test_invalid_commitment<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let keys = key_gen::<R, C>(&mut *rng);
|
||||
let machines = algorithm_machines(&mut *rng, MultiNonce::<C>::new(), &keys);
|
||||
let machines = algorithm_machines(&mut *rng, &MultiNonce::<C>::new(), &keys);
|
||||
let (machines, mut preprocesses) = preprocess(&mut *rng, machines, |_, _| {});
|
||||
|
||||
// Select a random participant to give an invalid commitment
|
||||
|
@ -193,7 +193,7 @@ pub fn test_invalid_commitment<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
|||
/// Test malleating the DLEq proof for a preprocess causes it to error.
|
||||
pub fn test_invalid_dleq_proof<R: RngCore + CryptoRng, C: Curve>(rng: &mut R) {
|
||||
let keys = key_gen::<R, C>(&mut *rng);
|
||||
let machines = algorithm_machines(&mut *rng, MultiNonce::<C>::new(), &keys);
|
||||
let machines = algorithm_machines(&mut *rng, &MultiNonce::<C>::new(), &keys);
|
||||
let (machines, mut preprocesses) = preprocess(&mut *rng, machines, |_, _| {});
|
||||
|
||||
// Select a random participant to give an invalid DLEq proof
|
||||
|
|
|
@ -143,12 +143,12 @@ fn vectors_to_multisig_keys<C: Curve>(vectors: &Vectors) -> HashMap<Participant,
|
|||
/// Test a Ciphersuite with its vectors.
|
||||
pub fn test_with_vectors<R: RngCore + CryptoRng, C: Curve, H: Hram<C>>(
|
||||
rng: &mut R,
|
||||
vectors: Vectors,
|
||||
vectors: &Vectors,
|
||||
) {
|
||||
test_ciphersuite::<R, C, H>(rng);
|
||||
|
||||
// Test against the vectors
|
||||
let keys = vectors_to_multisig_keys::<C>(&vectors);
|
||||
let keys = vectors_to_multisig_keys::<C>(vectors);
|
||||
{
|
||||
let group_key =
|
||||
<C as Curve>::read_G::<&[u8]>(&mut hex::decode(&vectors.group_key).unwrap().as_ref())
|
||||
|
|
|
@ -69,6 +69,7 @@ impl<C: Ciphersuite> SchnorrSignature<C> {
|
|||
/// This challenge must be properly crafted, which means being binding to the public key, nonce,
|
||||
/// and any message. Failure to do so will let a malicious adversary to forge signatures for
|
||||
/// different keys/messages.
|
||||
#[allow(clippy::needless_pass_by_value)] // Prevents further-use of this single-use value
|
||||
pub fn sign(
|
||||
private_key: &Zeroizing<C::F>,
|
||||
nonce: Zeroizing<C::F>,
|
||||
|
|
|
@ -17,8 +17,9 @@ fn test() {
|
|||
|
||||
let keys = key_gen(&mut OsRng);
|
||||
let key = keys[&Participant::new(1).unwrap()].group_key();
|
||||
let machines = algorithm_machines(&mut OsRng, Schnorrkel::new(CONTEXT), &keys);
|
||||
let signature = sign(&mut OsRng, Schnorrkel::new(CONTEXT), keys, machines, MSG);
|
||||
let algorithm = Schnorrkel::new(CONTEXT);
|
||||
let machines = algorithm_machines(&mut OsRng, &algorithm, &keys);
|
||||
let signature = sign(&mut OsRng, &algorithm, keys, machines, MSG);
|
||||
|
||||
let key = PublicKey::from_bytes(key.to_bytes().as_ref()).unwrap();
|
||||
key.verify(&mut SigningContext::new(CONTEXT).bytes(MSG), &signature).unwrap()
|
||||
|
|
|
@ -50,6 +50,7 @@ pub trait Transcript: Send + Clone {
|
|||
fn rng_seed(&mut self, label: &'static [u8]) -> [u8; 32];
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
enum DigestTranscriptMember {
|
||||
Name,
|
||||
Domain,
|
||||
|
|
|
@ -54,7 +54,7 @@ pub(crate) use self::clippy::*;
|
|||
*/
|
||||
pub(crate) fn queue_message(
|
||||
db: &mut Db,
|
||||
meta: Metadata,
|
||||
meta: &Metadata,
|
||||
msg: Vec<u8>,
|
||||
sig: SchnorrSignature<Ristretto>,
|
||||
) {
|
||||
|
@ -115,7 +115,7 @@ pub(crate) fn queue_message(
|
|||
pub(crate) fn get_next_message(from: Service, to: Service) -> Option<QueuedMessage> {
|
||||
let queue_outer = QUEUES.read().unwrap();
|
||||
let queue = queue_outer[&(from, to)].read().unwrap();
|
||||
let next = queue.last_acknowledged().map(|i| i + 1).unwrap_or(0);
|
||||
let next = queue.last_acknowledged().map_or(0, |i| i + 1);
|
||||
queue.get_message(next)
|
||||
}
|
||||
|
||||
|
@ -246,7 +246,7 @@ async fn main() {
|
|||
MessageQueueRequest::Queue { meta, msg, sig } => {
|
||||
queue_message(
|
||||
&mut db,
|
||||
meta,
|
||||
&meta,
|
||||
msg,
|
||||
SchnorrSignature::<Ristretto>::read(&mut sig.as_slice()).unwrap(),
|
||||
);
|
||||
|
|
|
@ -16,8 +16,7 @@ impl<D: Db> Queue<D> {
|
|||
self
|
||||
.0
|
||||
.get(self.message_count_key())
|
||||
.map(|bytes| u64::from_le_bytes(bytes.try_into().unwrap()))
|
||||
.unwrap_or(0)
|
||||
.map_or(0, |bytes| u64::from_le_bytes(bytes.try_into().unwrap()))
|
||||
}
|
||||
|
||||
fn last_acknowledged_key(&self) -> Vec<u8> {
|
||||
|
|
|
@ -130,8 +130,8 @@ pub mod sign {
|
|||
|
||||
pub fn session(&self) -> Session {
|
||||
match self {
|
||||
CoordinatorMessage::Preprocesses { id, .. } => id.session,
|
||||
CoordinatorMessage::Shares { id, .. } => id.session,
|
||||
CoordinatorMessage::Preprocesses { id, .. } |
|
||||
CoordinatorMessage::Shares { id, .. } |
|
||||
CoordinatorMessage::Reattempt { id } => id.session,
|
||||
CoordinatorMessage::Completed { session, .. } => *session,
|
||||
}
|
||||
|
@ -193,12 +193,7 @@ pub mod coordinator {
|
|||
// network *and the local node*
|
||||
// This synchrony obtained lets us ignore the synchrony requirement offered here
|
||||
pub fn required_block(&self) -> Option<BlockHash> {
|
||||
match self {
|
||||
CoordinatorMessage::CosignSubstrateBlock { .. } => None,
|
||||
CoordinatorMessage::SubstratePreprocesses { .. } => None,
|
||||
CoordinatorMessage::SubstrateShares { .. } => None,
|
||||
CoordinatorMessage::BatchReattempt { .. } => None,
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +235,7 @@ pub mod substrate {
|
|||
impl CoordinatorMessage {
|
||||
pub fn required_block(&self) -> Option<BlockHash> {
|
||||
let context = match self {
|
||||
CoordinatorMessage::ConfirmKeyPair { context, .. } => context,
|
||||
CoordinatorMessage::ConfirmKeyPair { context, .. } |
|
||||
CoordinatorMessage::SubstrateBlock { context, .. } => context,
|
||||
};
|
||||
Some(context.network_latest_finalized_block)
|
||||
|
|
|
@ -111,7 +111,7 @@ impl<D: Db> BatchSigner<D> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
async fn attempt(
|
||||
fn attempt(
|
||||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
id: u32,
|
||||
|
@ -189,11 +189,7 @@ impl<D: Db> BatchSigner<D> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub async fn sign(
|
||||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
batch: Batch,
|
||||
) -> Option<ProcessorMessage> {
|
||||
pub fn sign(&mut self, txn: &mut D::Transaction<'_>, batch: Batch) -> Option<ProcessorMessage> {
|
||||
debug_assert_eq!(self.network, batch.network);
|
||||
let id = batch.id;
|
||||
if CompletedDb::get(txn, id).is_some() {
|
||||
|
@ -203,11 +199,11 @@ impl<D: Db> BatchSigner<D> {
|
|||
}
|
||||
|
||||
self.signable.insert(id, batch);
|
||||
self.attempt(txn, id, 0).await
|
||||
self.attempt(txn, id, 0)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub async fn handle(
|
||||
pub fn handle(
|
||||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
msg: CoordinatorMessage,
|
||||
|
@ -394,7 +390,7 @@ impl<D: Db> BatchSigner<D> {
|
|||
let SubstrateSignableId::Batch(batch_id) = id.id else {
|
||||
panic!("BatchReattempt passed non-Batch ID")
|
||||
};
|
||||
self.attempt(txn, batch_id, id.attempt).await.map(Into::into)
|
||||
self.attempt(txn, batch_id, id.attempt).map(Into::into)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ impl Cosigner {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub async fn handle(
|
||||
pub fn handle(
|
||||
&mut self,
|
||||
txn: &mut impl DbTxn,
|
||||
msg: CoordinatorMessage,
|
||||
|
|
|
@ -32,7 +32,7 @@ impl PendingActivationsDb {
|
|||
}
|
||||
pub fn set_pending_activation<N: Network>(
|
||||
txn: &mut impl DbTxn,
|
||||
block_before_queue_block: <N::Block as Block<N>>::Id,
|
||||
block_before_queue_block: &<N::Block as Block<N>>::Id,
|
||||
session: Session,
|
||||
key_pair: KeyPair,
|
||||
) {
|
||||
|
|
|
@ -89,7 +89,7 @@ impl KeysDb {
|
|||
fn confirm_keys<N: Network>(
|
||||
txn: &mut impl DbTxn,
|
||||
session: Session,
|
||||
key_pair: KeyPair,
|
||||
key_pair: &KeyPair,
|
||||
) -> (Vec<ThresholdKeys<Ristretto>>, Vec<ThresholdKeys<N::Curve>>) {
|
||||
let (keys_vec, keys) = GeneratedKeysDb::read_keys::<N>(
|
||||
txn,
|
||||
|
@ -175,7 +175,7 @@ impl<N: Network, D: Db> KeyGen<N, D> {
|
|||
KeysDb::substrate_keys_by_session::<N>(&self.db, session)
|
||||
}
|
||||
|
||||
pub async fn handle(
|
||||
pub fn handle(
|
||||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
msg: CoordinatorMessage,
|
||||
|
@ -582,11 +582,13 @@ impl<N: Network, D: Db> KeyGen<N, D> {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn confirm(
|
||||
// This should only be called if we're participating, hence taking our instance
|
||||
#[allow(clippy::unused_self)]
|
||||
pub fn confirm(
|
||||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
session: Session,
|
||||
key_pair: KeyPair,
|
||||
key_pair: &KeyPair,
|
||||
) -> KeyConfirmed<N::Curve> {
|
||||
info!(
|
||||
"Confirmed key pair {} {} for {:?}",
|
||||
|
|
|
@ -199,7 +199,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
if tributary_mutable.key_gen.in_set(&session) {
|
||||
// See TributaryMutable's struct definition for why this block is safe
|
||||
let KeyConfirmed { substrate_keys, network_keys } =
|
||||
tributary_mutable.key_gen.confirm(txn, session, key_pair.clone()).await;
|
||||
tributary_mutable.key_gen.confirm(txn, session, &key_pair);
|
||||
if session.0 == 0 {
|
||||
tributary_mutable.batch_signer =
|
||||
Some(BatchSigner::new(N::NETWORK, session, substrate_keys));
|
||||
|
@ -214,7 +214,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
|
||||
match msg.msg.clone() {
|
||||
CoordinatorMessage::KeyGen(msg) => {
|
||||
coordinator.send(tributary_mutable.key_gen.handle(txn, msg).await).await;
|
||||
coordinator.send(tributary_mutable.key_gen.handle(txn, msg)).await;
|
||||
}
|
||||
|
||||
CoordinatorMessage::Sign(msg) => {
|
||||
|
@ -232,9 +232,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
CoordinatorMessage::Coordinator(msg) => {
|
||||
let is_batch = match msg {
|
||||
CoordinatorCoordinatorMessage::CosignSubstrateBlock { .. } => false,
|
||||
CoordinatorCoordinatorMessage::SubstratePreprocesses { ref id, .. } => {
|
||||
matches!(&id.id, SubstrateSignableId::Batch(_))
|
||||
}
|
||||
CoordinatorCoordinatorMessage::SubstratePreprocesses { ref id, .. } |
|
||||
CoordinatorCoordinatorMessage::SubstrateShares { ref id, .. } => {
|
||||
matches!(&id.id, SubstrateSignableId::Batch(_))
|
||||
}
|
||||
|
@ -248,7 +246,6 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
"coordinator told us to sign a batch when we don't currently have a Substrate signer",
|
||||
)
|
||||
.handle(txn, msg)
|
||||
.await
|
||||
{
|
||||
coordinator.send(msg).await;
|
||||
}
|
||||
|
@ -272,7 +269,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
}
|
||||
_ => {
|
||||
if let Some(cosigner) = tributary_mutable.cosigner.as_mut() {
|
||||
if let Some(msg) = cosigner.handle(txn, msg).await {
|
||||
if let Some(msg) = cosigner.handle(txn, msg) {
|
||||
coordinator.send(msg).await;
|
||||
}
|
||||
} else {
|
||||
|
@ -355,7 +352,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
// Set this variable so when we get the next Batch event, we can handle it
|
||||
PendingActivationsDb::set_pending_activation::<N>(
|
||||
txn,
|
||||
block_before_queue_block,
|
||||
&block_before_queue_block,
|
||||
session,
|
||||
key_pair,
|
||||
);
|
||||
|
@ -429,7 +426,7 @@ async fn handle_coordinator_msg<D: Db, N: Network, Co: Coordinator>(
|
|||
for (key, id, tx, eventuality) in to_sign {
|
||||
if let Some(session) = SessionDb::get(txn, key.to_bytes().as_ref()) {
|
||||
let signer = signers.get_mut(&session).unwrap();
|
||||
if let Some(msg) = signer.sign_transaction(txn, id, tx, eventuality).await {
|
||||
if let Some(msg) = signer.sign_transaction(txn, id, tx, &eventuality).await {
|
||||
coordinator.send(msg).await;
|
||||
}
|
||||
}
|
||||
|
@ -521,7 +518,7 @@ async fn boot<N: Network, D: Db, Co: Coordinator>(
|
|||
if plan.key == network_key {
|
||||
let mut txn = raw_db.txn();
|
||||
if let Some(msg) =
|
||||
signer.sign_transaction(&mut txn, plan.id(), tx.clone(), eventuality.clone()).await
|
||||
signer.sign_transaction(&mut txn, plan.id(), tx.clone(), eventuality).await
|
||||
{
|
||||
coordinator.send(msg).await;
|
||||
}
|
||||
|
@ -622,7 +619,7 @@ async fn run<N: Network, D: Db, Co: Coordinator>(mut raw_db: D, network: N, mut
|
|||
).await;
|
||||
|
||||
if let Some(batch_signer) = tributary_mutable.batch_signer.as_mut() {
|
||||
if let Some(msg) = batch_signer.sign(&mut txn, batch).await {
|
||||
if let Some(msg) = batch_signer.sign(&mut txn, batch) {
|
||||
coordinator.send(msg).await;
|
||||
}
|
||||
}
|
||||
|
@ -644,7 +641,7 @@ async fn run<N: Network, D: Db, Co: Coordinator>(mut raw_db: D, network: N, mut
|
|||
MultisigEvent::Completed(key, id, tx) => {
|
||||
if let Some(session) = SessionDb::get(&txn, &key) {
|
||||
let signer = tributary_mutable.signers.get_mut(&session).unwrap();
|
||||
if let Some(msg) = signer.completed(&mut txn, id, tx) {
|
||||
if let Some(msg) = signer.completed(&mut txn, id, &tx) {
|
||||
coordinator.send(msg).await;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ impl ResolvedDb {
|
|||
txn: &mut impl DbTxn,
|
||||
key: &[u8],
|
||||
plan: [u8; 32],
|
||||
resolution: <N::Transaction as Transaction<N>>::Id,
|
||||
resolution: &<N::Transaction as Transaction<N>>::Id,
|
||||
) {
|
||||
let mut signing = SigningDb::get(txn, key).unwrap_or_default();
|
||||
assert_eq!(signing.len() % 32, 0);
|
||||
|
@ -160,7 +160,7 @@ impl PlansFromScanningDb {
|
|||
}
|
||||
|
||||
impl ForwardedOutputDb {
|
||||
pub fn save_forwarded_output(txn: &mut impl DbTxn, instruction: InInstructionWithBalance) {
|
||||
pub fn save_forwarded_output(txn: &mut impl DbTxn, instruction: &InInstructionWithBalance) {
|
||||
let mut existing = Self::get(txn, instruction.balance).unwrap_or_default();
|
||||
existing.extend(instruction.encode());
|
||||
Self::set(txn, instruction.balance, &existing);
|
||||
|
@ -184,7 +184,7 @@ impl ForwardedOutputDb {
|
|||
}
|
||||
|
||||
impl DelayedOutputDb {
|
||||
pub fn save_delayed_output(txn: &mut impl DbTxn, instruction: InInstructionWithBalance) {
|
||||
pub fn save_delayed_output(txn: &mut impl DbTxn, instruction: &InInstructionWithBalance) {
|
||||
let mut existing = Self::get(txn).unwrap_or_default();
|
||||
existing.extend(instruction.encode());
|
||||
Self::set(txn, &existing);
|
||||
|
|
|
@ -7,7 +7,7 @@ use scale::{Encode, Decode};
|
|||
use messages::SubstrateContext;
|
||||
|
||||
use serai_client::{
|
||||
primitives::{MAX_DATA_LEN, NetworkId, Coin, ExternalAddress, BlockHash},
|
||||
primitives::{MAX_DATA_LEN, NetworkId, Coin, ExternalAddress, BlockHash, Data},
|
||||
in_instructions::primitives::{
|
||||
InInstructionWithBalance, Batch, RefundableInInstruction, Shorthand, MAX_BATCH_SIZE,
|
||||
},
|
||||
|
@ -316,7 +316,7 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
assert_eq!(balance.coin.network(), N::NETWORK);
|
||||
|
||||
if let Ok(address) = N::Address::try_from(address.consume()) {
|
||||
payments.push(Payment { address, data: data.map(|data| data.consume()), balance });
|
||||
payments.push(Payment { address, data: data.map(Data::consume), balance });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -513,7 +513,7 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
let mut plans = vec![];
|
||||
existing_outputs.retain(|output| {
|
||||
match output.kind() {
|
||||
OutputType::External => false,
|
||||
OutputType::External | OutputType::Forwarded => false,
|
||||
OutputType::Branch => {
|
||||
let scheduler = &mut self.existing.as_mut().unwrap().scheduler;
|
||||
// There *would* be a race condition here due to the fact we only mark a `Branch` output
|
||||
|
@ -576,7 +576,6 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
}
|
||||
false
|
||||
}
|
||||
OutputType::Forwarded => false,
|
||||
}
|
||||
});
|
||||
plans
|
||||
|
@ -873,7 +872,7 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
// letting it die out
|
||||
if let Some(tx) = &tx {
|
||||
instruction.balance.amount.0 -= tx.0.fee();
|
||||
ForwardedOutputDb::save_forwarded_output(txn, instruction);
|
||||
ForwardedOutputDb::save_forwarded_output(txn, &instruction);
|
||||
}
|
||||
} else if let Some(refund_to) = refund_to {
|
||||
if let Ok(refund_to) = refund_to.consume().try_into() {
|
||||
|
@ -907,9 +906,7 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
}
|
||||
|
||||
let (refund_to, instruction) = instruction_from_output::<N>(&output);
|
||||
let instruction = if let Some(instruction) = instruction {
|
||||
instruction
|
||||
} else {
|
||||
let Some(instruction) = instruction else {
|
||||
if let Some(refund_to) = refund_to {
|
||||
if let Ok(refund_to) = refund_to.consume().try_into() {
|
||||
plans.push(Self::refund_plan(output.clone(), refund_to));
|
||||
|
@ -922,7 +919,7 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
if Some(output.key()) == self.new.as_ref().map(|new| new.key) {
|
||||
match step {
|
||||
RotationStep::UseExisting => {
|
||||
DelayedOutputDb::save_delayed_output(txn, instruction);
|
||||
DelayedOutputDb::save_delayed_output(txn, &instruction);
|
||||
continue;
|
||||
}
|
||||
RotationStep::NewAsChange |
|
||||
|
@ -1003,7 +1000,7 @@ impl<D: Db, N: Network> MultisigManager<D, N> {
|
|||
// within the block. Unknown Eventualities may have their Completed events emitted after
|
||||
// ScannerEvent::Block however.
|
||||
ScannerEvent::Completed(key, block_number, id, tx) => {
|
||||
ResolvedDb::resolve_plan::<N>(txn, &key, id, tx.id());
|
||||
ResolvedDb::resolve_plan::<N>(txn, &key, id, &tx.id());
|
||||
(block_number, MultisigEvent::Completed(key, id, tx))
|
||||
}
|
||||
};
|
||||
|
|
|
@ -415,7 +415,7 @@ impl<N: Network, D: Db> Scanner<N, D> {
|
|||
)
|
||||
}
|
||||
|
||||
async fn emit(&mut self, event: ScannerEvent<N>) -> bool {
|
||||
fn emit(&mut self, event: ScannerEvent<N>) -> bool {
|
||||
if self.events.send(event).is_err() {
|
||||
info!("Scanner handler was dropped. Shutting down?");
|
||||
return false;
|
||||
|
@ -496,12 +496,9 @@ impl<N: Network, D: Db> Scanner<N, D> {
|
|||
}
|
||||
}
|
||||
|
||||
let block = match network.get_block(block_being_scanned).await {
|
||||
Ok(block) => block,
|
||||
Err(_) => {
|
||||
warn!("couldn't get block {block_being_scanned}");
|
||||
break;
|
||||
}
|
||||
let Ok(block) = network.get_block(block_being_scanned).await else {
|
||||
warn!("couldn't get block {block_being_scanned}");
|
||||
break;
|
||||
};
|
||||
let block_id = block.id();
|
||||
|
||||
|
@ -570,7 +567,7 @@ impl<N: Network, D: Db> Scanner<N, D> {
|
|||
|
||||
completion_block_numbers.push(block_number);
|
||||
// This must be before the mission of ScannerEvent::Block, per commentary in mod.rs
|
||||
if !scanner.emit(ScannerEvent::Completed(key_vec.clone(), block_number, id, tx)).await {
|
||||
if !scanner.emit(ScannerEvent::Completed(key_vec.clone(), block_number, id, tx)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -687,10 +684,7 @@ impl<N: Network, D: Db> Scanner<N, D> {
|
|||
txn.commit();
|
||||
|
||||
// Send all outputs
|
||||
if !scanner
|
||||
.emit(ScannerEvent::Block { is_retirement_block, block: block_id, outputs })
|
||||
.await
|
||||
{
|
||||
if !scanner.emit(ScannerEvent::Block { is_retirement_block, block: block_id, outputs }) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -335,7 +335,7 @@ impl<N: Network> Scheduler<N> {
|
|||
// Since we do multiple aggregation TXs at once, this will execute in logarithmic time
|
||||
let utxos = self.utxos.drain(..).collect::<Vec<_>>();
|
||||
let mut utxo_chunks =
|
||||
utxos.chunks(N::MAX_INPUTS).map(|chunk| chunk.to_vec()).collect::<Vec<_>>();
|
||||
utxos.chunks(N::MAX_INPUTS).map(<[<N as Network>::Output]>::to_vec).collect::<Vec<_>>();
|
||||
|
||||
// Use the first chunk for any scheduled payments, since it has the most value
|
||||
let utxos = utxo_chunks.remove(0);
|
||||
|
@ -456,10 +456,7 @@ impl<N: Network> Scheduler<N> {
|
|||
}
|
||||
|
||||
// If we didn't actually create this output, return, dropping the child payments
|
||||
let actual = match actual {
|
||||
Some(actual) => actual,
|
||||
None => return,
|
||||
};
|
||||
let Some(actual) = actual else { return };
|
||||
|
||||
// Amortize the fee amongst all payments underneath this branch
|
||||
{
|
||||
|
|
|
@ -427,7 +427,7 @@ impl Bitcoin {
|
|||
match BSignableTransaction::new(
|
||||
inputs.iter().map(|input| input.output.clone()).collect(),
|
||||
&payments,
|
||||
change.as_ref().map(|change| change.0.clone()),
|
||||
change.as_ref().map(|change| &change.0),
|
||||
None,
|
||||
fee.0,
|
||||
) {
|
||||
|
@ -435,16 +435,14 @@ impl Bitcoin {
|
|||
Err(TransactionError::NoInputs) => {
|
||||
panic!("trying to create a bitcoin transaction without inputs")
|
||||
}
|
||||
// No outputs left and the change isn't worth enough
|
||||
Err(TransactionError::NoOutputs) => Ok(None),
|
||||
// No outputs left and the change isn't worth enough/not even enough funds to pay the fee
|
||||
Err(TransactionError::NoOutputs | TransactionError::NotEnoughFunds) => Ok(None),
|
||||
// amortize_fee removes payments which fall below the dust threshold
|
||||
Err(TransactionError::DustPayment) => panic!("dust payment despite removing dust"),
|
||||
Err(TransactionError::TooMuchData) => panic!("too much data despite not specifying data"),
|
||||
Err(TransactionError::TooLowFee) => {
|
||||
panic!("created a transaction whose fee is below the minimum")
|
||||
}
|
||||
// Mot even enough funds to pay the fee
|
||||
Err(TransactionError::NotEnoughFunds) => Ok(None),
|
||||
Err(TransactionError::TooLargeTransaction) => {
|
||||
panic!("created a too large transaction despite limiting inputs/outputs")
|
||||
}
|
||||
|
@ -637,7 +635,7 @@ impl Network for Bitcoin {
|
|||
return res;
|
||||
}
|
||||
|
||||
async fn check_block(
|
||||
fn check_block(
|
||||
eventualities: &mut EventualitiesTracker<Eventuality>,
|
||||
block: &Block,
|
||||
res: &mut HashMap<[u8; 32], (usize, Transaction)>,
|
||||
|
@ -678,11 +676,11 @@ impl Network for Bitcoin {
|
|||
block.unwrap()
|
||||
};
|
||||
|
||||
check_block(eventualities, &block, &mut res).await;
|
||||
check_block(eventualities, &block, &mut res);
|
||||
}
|
||||
|
||||
// Also check the current block
|
||||
check_block(eventualities, block, &mut res).await;
|
||||
check_block(eventualities, block, &mut res);
|
||||
assert_eq!(eventualities.block_number, this_block_num);
|
||||
|
||||
res
|
||||
|
@ -733,7 +731,7 @@ impl Network for Bitcoin {
|
|||
transaction
|
||||
.actual
|
||||
.clone()
|
||||
.multisig(keys.clone(), transaction.transcript)
|
||||
.multisig(&keys, transaction.transcript)
|
||||
.expect("used the wrong keys"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -229,6 +229,7 @@ impl PartialEq for Monero {
|
|||
}
|
||||
impl Eq for Monero {}
|
||||
|
||||
#[allow(clippy::needless_pass_by_value)] // Needed to satisfy API expectations
|
||||
fn map_rpc_err(err: RpcError) -> NetworkError {
|
||||
if let RpcError::InvalidNode(reason) = &err {
|
||||
log::error!("Monero RpcError::InvalidNode({reason})");
|
||||
|
@ -384,7 +385,7 @@ impl Monero {
|
|||
Some(Zeroizing::new(*plan_id)),
|
||||
inputs.clone(),
|
||||
payments,
|
||||
Change::fingerprintable(change.as_ref().map(|change| change.clone().into())),
|
||||
&Change::fingerprintable(change.as_ref().map(|change| change.clone().into())),
|
||||
vec![],
|
||||
fee_rate,
|
||||
) {
|
||||
|
@ -657,7 +658,7 @@ impl Network for Monero {
|
|||
keys: ThresholdKeys<Self::Curve>,
|
||||
transaction: SignableTransaction,
|
||||
) -> Result<Self::TransactionMachine, NetworkError> {
|
||||
match transaction.actual.clone().multisig(keys, transaction.transcript) {
|
||||
match transaction.actual.clone().multisig(&keys, transaction.transcript) {
|
||||
Ok(machine) => Ok(machine),
|
||||
Err(e) => panic!("failed to create a multisig machine for TX: {e}"),
|
||||
}
|
||||
|
@ -753,7 +754,7 @@ impl Network for Monero {
|
|||
None,
|
||||
inputs,
|
||||
vec![(address.into(), amount - fee)],
|
||||
Change::fingerprintable(Some(Self::test_address().into())),
|
||||
&Change::fingerprintable(Some(Self::test_address().into())),
|
||||
vec![],
|
||||
self.rpc.get_fee(protocol, FeePriority::Low).await.unwrap(),
|
||||
)
|
||||
|
|
|
@ -99,7 +99,7 @@ impl<N: Network> core::fmt::Debug for Plan<N> {
|
|||
.field("key", &hex::encode(self.key.to_bytes()))
|
||||
.field("inputs", &self.inputs)
|
||||
.field("payments", &self.payments)
|
||||
.field("change", &self.change.as_ref().map(|change| change.to_string()))
|
||||
.field("change", &self.change.as_ref().map(ToString::to_string))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,11 @@ impl CompletionsDb {
|
|||
}
|
||||
|
||||
impl EventualityDb {
|
||||
fn save_eventuality<N: Network>(txn: &mut impl DbTxn, id: [u8; 32], eventuality: N::Eventuality) {
|
||||
fn save_eventuality<N: Network>(
|
||||
txn: &mut impl DbTxn,
|
||||
id: [u8; 32],
|
||||
eventuality: &N::Eventuality,
|
||||
) {
|
||||
txn.put(Self::key(id), eventuality.serialize());
|
||||
}
|
||||
|
||||
|
@ -113,7 +117,7 @@ impl TransactionDb {
|
|||
|
||||
fn transaction<N: Network>(
|
||||
getter: &impl Get,
|
||||
id: <N::Transaction as Transaction<N>>::Id,
|
||||
id: &<N::Transaction as Transaction<N>>::Id,
|
||||
) -> Option<N::Transaction> {
|
||||
Self::get(getter, id.as_ref()).map(|tx| N::Transaction::read(&mut tx.as_slice()).unwrap())
|
||||
}
|
||||
|
@ -164,7 +168,7 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
log::info!("rebroadcasting {}", hex::encode(&completion));
|
||||
// TODO: Don't drop the error entirely. Check for invariants
|
||||
let _ = network
|
||||
.publish_transaction(&TransactionDb::transaction::<N>(&db, completion).unwrap())
|
||||
.publish_transaction(&TransactionDb::transaction::<N>(&db, &completion).unwrap())
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +225,7 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
fn already_completed(&self, txn: &mut D::Transaction<'_>, id: [u8; 32]) -> bool {
|
||||
fn already_completed(txn: &mut D::Transaction<'_>, id: [u8; 32]) -> bool {
|
||||
if !CompletionsDb::completions::<N>(txn, id).is_empty() {
|
||||
debug!(
|
||||
"SignTransaction/Reattempt order for {}, which we've already completed signing",
|
||||
|
@ -238,7 +242,7 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
fn complete(
|
||||
&mut self,
|
||||
id: [u8; 32],
|
||||
tx_id: <N::Transaction as Transaction<N>>::Id,
|
||||
tx_id: &<N::Transaction as Transaction<N>>::Id,
|
||||
) -> ProcessorMessage {
|
||||
// Assert we're actively signing for this TX
|
||||
assert!(self.signable.remove(&id).is_some(), "completed a TX we weren't signing for");
|
||||
|
@ -260,16 +264,16 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
&mut self,
|
||||
txn: &mut D::Transaction<'_>,
|
||||
id: [u8; 32],
|
||||
tx: N::Transaction,
|
||||
tx: &N::Transaction,
|
||||
) -> Option<ProcessorMessage> {
|
||||
let first_completion = !self.already_completed(txn, id);
|
||||
let first_completion = !Self::already_completed(txn, id);
|
||||
|
||||
// Save this completion to the DB
|
||||
CompletedOnChainDb::complete_on_chain(txn, &id);
|
||||
CompletionsDb::complete::<N>(txn, id, &tx);
|
||||
CompletionsDb::complete::<N>(txn, id, tx);
|
||||
|
||||
if first_completion {
|
||||
Some(self.complete(id, tx.id()))
|
||||
Some(self.complete(id, &tx.id()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -302,13 +306,13 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
if self.network.confirm_completion(&eventuality, &tx) {
|
||||
info!("signer eventuality for {} resolved in TX {}", hex::encode(id), hex::encode(tx_id));
|
||||
|
||||
let first_completion = !self.already_completed(txn, id);
|
||||
let first_completion = !Self::already_completed(txn, id);
|
||||
|
||||
// Save this completion to the DB
|
||||
CompletionsDb::complete::<N>(txn, id, &tx);
|
||||
|
||||
if first_completion {
|
||||
return Some(self.complete(id, tx.id()));
|
||||
return Some(self.complete(id, &tx.id()));
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
|
@ -337,7 +341,7 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
id: [u8; 32],
|
||||
attempt: u32,
|
||||
) -> Option<ProcessorMessage> {
|
||||
if self.already_completed(txn, id) {
|
||||
if Self::already_completed(txn, id) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -427,13 +431,13 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
txn: &mut D::Transaction<'_>,
|
||||
id: [u8; 32],
|
||||
tx: N::SignableTransaction,
|
||||
eventuality: N::Eventuality,
|
||||
eventuality: &N::Eventuality,
|
||||
) -> Option<ProcessorMessage> {
|
||||
// The caller is expected to re-issue sign orders on reboot
|
||||
// This is solely used by the rebroadcast task
|
||||
ActiveSignsDb::add_active_sign(txn, &id);
|
||||
|
||||
if self.already_completed(txn, id) {
|
||||
if Self::already_completed(txn, id) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -596,7 +600,7 @@ impl<N: Network, D: Db> Signer<N, D> {
|
|||
}
|
||||
|
||||
// Stop trying to sign for this TX
|
||||
Some(self.complete(id.id, tx_id))
|
||||
Some(self.complete(id.id, &tx_id))
|
||||
}
|
||||
|
||||
CoordinatorMessage::Reattempt { id } => self.attempt(txn, id.id, id.attempt).await,
|
||||
|
|
|
@ -23,8 +23,8 @@ use messages::{
|
|||
};
|
||||
use crate::batch_signer::BatchSigner;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_batch_signer() {
|
||||
#[test]
|
||||
fn test_batch_signer() {
|
||||
let keys = key_gen::<_, Ristretto>(&mut OsRng);
|
||||
|
||||
let participant_one = Participant::new(1).unwrap();
|
||||
|
@ -74,7 +74,7 @@ async fn test_batch_signer() {
|
|||
let mut db = MemDb::new();
|
||||
|
||||
let mut txn = db.txn();
|
||||
match signer.sign(&mut txn, batch.clone()).await.unwrap() {
|
||||
match signer.sign(&mut txn, batch.clone()).unwrap() {
|
||||
// All participants should emit a preprocess
|
||||
coordinator::ProcessorMessage::BatchPreprocess {
|
||||
id,
|
||||
|
@ -109,7 +109,6 @@ async fn test_batch_signer() {
|
|||
preprocesses: clone_without(&preprocesses, i),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
ProcessorMessage::Coordinator(coordinator::ProcessorMessage::SubstrateShare {
|
||||
|
@ -137,7 +136,6 @@ async fn test_batch_signer() {
|
|||
shares: clone_without(&shares, i),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
ProcessorMessage::Substrate(substrate::ProcessorMessage::SignedBatch {
|
||||
|
|
|
@ -18,8 +18,8 @@ use serai_client::{primitives::*, validator_sets::primitives::Session};
|
|||
use messages::coordinator::*;
|
||||
use crate::cosigner::Cosigner;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_cosigner() {
|
||||
#[test]
|
||||
fn test_cosigner() {
|
||||
let keys = key_gen::<_, Ristretto>(&mut OsRng);
|
||||
|
||||
let participant_one = Participant::new(1).unwrap();
|
||||
|
@ -88,7 +88,6 @@ async fn test_cosigner() {
|
|||
preprocesses: clone_without(&preprocesses, i),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
ProcessorMessage::SubstrateShare { id, shares: mut these_shares } => {
|
||||
|
@ -113,7 +112,6 @@ async fn test_cosigner() {
|
|||
shares: clone_without(&shares, i),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
{
|
||||
ProcessorMessage::CosignedBlock { block_number, block: signed_block, signature } => {
|
||||
|
|
|
@ -20,7 +20,7 @@ use crate::{
|
|||
|
||||
const ID: KeyGenId = KeyGenId { session: Session(1), attempt: 3 };
|
||||
|
||||
pub async fn test_key_gen<N: Network>() {
|
||||
pub fn test_key_gen<N: Network>() {
|
||||
let mut entropies = HashMap::new();
|
||||
let mut dbs = HashMap::new();
|
||||
let mut key_gens = HashMap::new();
|
||||
|
@ -37,18 +37,15 @@ pub async fn test_key_gen<N: Network>() {
|
|||
for i in 1 ..= 5 {
|
||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||
let mut txn = dbs.get_mut(&i).unwrap().txn();
|
||||
if let ProcessorMessage::Commitments { id, mut commitments } = key_gen
|
||||
.handle(
|
||||
&mut txn,
|
||||
CoordinatorMessage::GenerateKey {
|
||||
id: ID,
|
||||
params: ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap())
|
||||
.unwrap(),
|
||||
shares: 1,
|
||||
},
|
||||
)
|
||||
.await
|
||||
{
|
||||
if let ProcessorMessage::Commitments { id, mut commitments } = key_gen.handle(
|
||||
&mut txn,
|
||||
CoordinatorMessage::GenerateKey {
|
||||
id: ID,
|
||||
params: ThresholdParams::new(3, 5, Participant::new(u16::try_from(i).unwrap()).unwrap())
|
||||
.unwrap(),
|
||||
shares: 1,
|
||||
},
|
||||
) {
|
||||
assert_eq!(id, ID);
|
||||
assert_eq!(commitments.len(), 1);
|
||||
all_commitments
|
||||
|
@ -74,16 +71,10 @@ pub async fn test_key_gen<N: Network>() {
|
|||
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||
let mut txn = dbs.get_mut(&i).unwrap().txn();
|
||||
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
||||
if let ProcessorMessage::Shares { id, mut shares } = key_gen
|
||||
.handle(
|
||||
&mut txn,
|
||||
CoordinatorMessage::Commitments {
|
||||
id: ID,
|
||||
commitments: clone_without(&all_commitments, &i),
|
||||
},
|
||||
)
|
||||
.await
|
||||
{
|
||||
if let ProcessorMessage::Shares { id, mut shares } = key_gen.handle(
|
||||
&mut txn,
|
||||
CoordinatorMessage::Commitments { id: ID, commitments: clone_without(&all_commitments, &i) },
|
||||
) {
|
||||
assert_eq!(id, ID);
|
||||
assert_eq!(shares.len(), 1);
|
||||
all_shares.insert(i, shares.swap_remove(0));
|
||||
|
@ -102,19 +93,16 @@ pub async fn test_key_gen<N: Network>() {
|
|||
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||
let mut txn = dbs.get_mut(&i).unwrap().txn();
|
||||
let i = Participant::new(u16::try_from(i).unwrap()).unwrap();
|
||||
if let ProcessorMessage::GeneratedKeyPair { id, substrate_key, network_key } = key_gen
|
||||
.handle(
|
||||
&mut txn,
|
||||
CoordinatorMessage::Shares {
|
||||
id: ID,
|
||||
shares: vec![all_shares
|
||||
.iter()
|
||||
.filter_map(|(l, shares)| if i == *l { None } else { Some((*l, shares[&i].clone())) })
|
||||
.collect()],
|
||||
},
|
||||
)
|
||||
.await
|
||||
{
|
||||
if let ProcessorMessage::GeneratedKeyPair { id, substrate_key, network_key } = key_gen.handle(
|
||||
&mut txn,
|
||||
CoordinatorMessage::Shares {
|
||||
id: ID,
|
||||
shares: vec![all_shares
|
||||
.iter()
|
||||
.filter_map(|(l, shares)| if i == *l { None } else { Some((*l, shares[&i].clone())) })
|
||||
.collect()],
|
||||
},
|
||||
) {
|
||||
assert_eq!(id, ID);
|
||||
if res.is_none() {
|
||||
res = Some((substrate_key, network_key.clone()));
|
||||
|
@ -134,13 +122,11 @@ pub async fn test_key_gen<N: Network>() {
|
|||
for i in 1 ..= 5 {
|
||||
let key_gen = key_gens.get_mut(&i).unwrap();
|
||||
let mut txn = dbs.get_mut(&i).unwrap().txn();
|
||||
let KeyConfirmed { mut substrate_keys, mut network_keys } = key_gen
|
||||
.confirm(
|
||||
&mut txn,
|
||||
ID.session,
|
||||
KeyPair(sr25519::Public(res.0), res.1.clone().try_into().unwrap()),
|
||||
)
|
||||
.await;
|
||||
let KeyConfirmed { mut substrate_keys, mut network_keys } = key_gen.confirm(
|
||||
&mut txn,
|
||||
ID.session,
|
||||
&KeyPair(sr25519::Public(res.0), res.1.clone().try_into().unwrap()),
|
||||
);
|
||||
txn.commit();
|
||||
|
||||
assert_eq!(substrate_keys.len(), 1);
|
||||
|
|
|
@ -46,7 +46,7 @@ macro_rules! test_network {
|
|||
#[tokio::test]
|
||||
async fn $key_gen() {
|
||||
init_logger();
|
||||
test_key_gen::<$N>().await;
|
||||
test_key_gen::<$N>();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -72,7 +72,7 @@ pub async fn sign<N: Network>(
|
|||
match signers
|
||||
.get_mut(&i)
|
||||
.unwrap()
|
||||
.sign_transaction(&mut txn, actual_id.id, tx, eventuality)
|
||||
.sign_transaction(&mut txn, actual_id.id, tx, &eventuality)
|
||||
.await
|
||||
{
|
||||
// All participants should emit a preprocess
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::common::{tx::publish_tx, validator_sets::set_keys};
|
|||
pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] {
|
||||
// TODO: Get the latest session
|
||||
let set = ValidatorSet { session: Session(0), network: batch.network };
|
||||
let pair = insecure_pair_from_name(&format!("ValidatorSet {:?}", set));
|
||||
let pair = insecure_pair_from_name(&format!("ValidatorSet {set:?}"));
|
||||
let keys = if let Some(keys) =
|
||||
serai.as_of_latest_finalized_block().await.unwrap().validator_sets().keys(set).await.unwrap()
|
||||
{
|
||||
|
|
|
@ -38,7 +38,7 @@ pub async fn set_keys(serai: &Serai, set: ValidatorSet, key_pair: KeyPair) -> [u
|
|||
&mut OsRng,
|
||||
frost::tests::algorithm_machines(
|
||||
&mut OsRng,
|
||||
Schnorrkel::new(b"substrate"),
|
||||
&Schnorrkel::new(b"substrate"),
|
||||
&HashMap::from([(threshold_keys.params().i(), threshold_keys.into())]),
|
||||
),
|
||||
&set_keys_message(&set, &[], &key_pair),
|
||||
|
|
|
@ -12,7 +12,8 @@ impl AllowMint for () {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)] // TODO: Investigate why Substrate generates this
|
||||
// TODO: Investigate why Substrate generates this
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
|
|
@ -94,7 +94,8 @@ use sp_std::prelude::*;
|
|||
pub use types::*;
|
||||
pub use weights::WeightInfo;
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)] // TODO: Investigate why Substrate generates this
|
||||
// TODO: Investigate why Substrate generates these
|
||||
#[allow(clippy::cast_possible_truncation, clippy::no_effect_underscore_binding)]
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use super::*;
|
||||
|
|
|
@ -74,7 +74,7 @@ fn check_pool_accounts_dont_collide() {
|
|||
for coin in coins() {
|
||||
let account = Dex::get_pool_account(coin);
|
||||
if map.contains(&account) {
|
||||
panic!("Collision at {:?}", coin);
|
||||
panic!("Collision at {coin:?}");
|
||||
}
|
||||
map.insert(account);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ use serai_primitives::{BlockHash, NetworkId};
|
|||
pub use in_instructions_primitives as primitives;
|
||||
use primitives::*;
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)] // TODO: Investigate why Substrate generates this
|
||||
// TODO: Investigate why Substrate generates these
|
||||
#[allow(clippy::cast_possible_truncation, clippy::no_effect_underscore_binding)]
|
||||
#[frame_support::pallet]
|
||||
pub mod pallet {
|
||||
use sp_std::vec;
|
||||
|
|
|
@ -100,7 +100,7 @@ pub fn run() -> sc_cli::Result<()> {
|
|||
if config.role.is_authority() {
|
||||
config.state_pruning = Some(PruningMode::ArchiveAll);
|
||||
}
|
||||
service::new_full(config).await.map_err(sc_cli::Error::Service)
|
||||
service::new_full(config).map_err(sc_cli::Error::Service)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue