Replace usage of io::Error::new(io::ErrorKind::Other, with io::Error::other

Newly possible with Rust 1.74.
This commit is contained in:
Luke Parker 2023-11-19 18:01:13 -05:00
parent 05b975dff9
commit 797604ad73
No known key found for this signature in database
25 changed files with 114 additions and 154 deletions

View file

@ -91,10 +91,8 @@ impl ReceivedOutput {
pub fn read<R: Read>(r: &mut R) -> io::Result<ReceivedOutput> { pub fn read<R: Read>(r: &mut R) -> io::Result<ReceivedOutput> {
Ok(ReceivedOutput { Ok(ReceivedOutput {
offset: Secp256k1::read_F(r)?, offset: Secp256k1::read_F(r)?,
output: TxOut::consensus_decode(r) output: TxOut::consensus_decode(r).map_err(|_| io::Error::other("invalid TxOut"))?,
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid TxOut"))?, outpoint: OutPoint::consensus_decode(r).map_err(|_| io::Error::other("invalid OutPoint"))?,
outpoint: OutPoint::consensus_decode(r)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid OutPoint"))?,
}) })
} }

View file

@ -304,7 +304,7 @@ async_sequential! {
} }
// Make sure the change is correct // Make sure the change is correct
assert_eq!(needed_fee, u64::try_from(tx.weight()).unwrap() * FEE); assert_eq!(needed_fee, u64::from(tx.weight()) * FEE);
let input_value = output.value() + offset_output.value(); let input_value = output.value() + offset_output.value();
let output_value = tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>(); let output_value = tx.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
assert_eq!(input_value - output_value, needed_fee); assert_eq!(input_value - output_value, needed_fee);

View file

@ -141,7 +141,7 @@ impl Protocol {
0 => match read_byte(r)? { 0 => match read_byte(r)? {
14 => Protocol::v14, 14 => Protocol::v14,
16 => Protocol::v16, 16 => Protocol::v16,
_ => Err(io::Error::new(io::ErrorKind::Other, "unrecognized monero protocol"))?, _ => Err(io::Error::other("unrecognized monero protocol"))?,
}, },
// Custom // Custom
1 => match read_byte(r)? { 1 => match read_byte(r)? {
@ -150,26 +150,24 @@ impl Protocol {
bp_plus: match read_byte(r)? { bp_plus: match read_byte(r)? {
0 => false, 0 => false,
1 => true, 1 => true,
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid bool serialization"))?, _ => Err(io::Error::other("invalid bool serialization"))?,
}, },
optimal_rct_type: RctType::from_byte(read_byte(r)?) optimal_rct_type: RctType::from_byte(read_byte(r)?)
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid RctType serialization"))?, .ok_or_else(|| io::Error::other("invalid RctType serialization"))?,
view_tags: match read_byte(r)? { view_tags: match read_byte(r)? {
0 => false, 0 => false,
1 => true, 1 => true,
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid bool serialization"))?, _ => Err(io::Error::other("invalid bool serialization"))?,
}, },
v16_fee: match read_byte(r)? { v16_fee: match read_byte(r)? {
0 => false, 0 => false,
1 => true, 1 => true,
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid bool serialization"))?, _ => Err(io::Error::other("invalid bool serialization"))?,
}, },
}, },
_ => { _ => Err(io::Error::other("unrecognized custom protocol serialization"))?,
Err(io::Error::new(io::ErrorKind::Other, "unrecognized custom protocol serialization"))?
}
}, },
_ => Err(io::Error::new(io::ErrorKind::Other, "unrecognized protocol serialization"))?, _ => Err(io::Error::other("unrecognized protocol serialization"))?,
}) })
} }
} }

View file

@ -184,10 +184,10 @@ impl Algorithm<Ed25519> for ClsagMultisig {
reader.read_exact(&mut bytes)?; reader.read_exact(&mut bytes)?;
// dfg ensures the point is torsion free // dfg ensures the point is torsion free
let xH = Option::<dfg::EdwardsPoint>::from(dfg::EdwardsPoint::from_bytes(&bytes)) let xH = Option::<dfg::EdwardsPoint>::from(dfg::EdwardsPoint::from_bytes(&bytes))
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid key image"))?; .ok_or_else(|| io::Error::other("invalid key image"))?;
// Ensure this is a canonical point // Ensure this is a canonical point
if xH.to_bytes() != bytes { if xH.to_bytes() != bytes {
Err(io::Error::new(io::ErrorKind::Other, "non-canonical key image"))?; Err(io::Error::other("non-canonical key image"))?;
} }
Ok(ClsagAddendum { key_image: xH, dleq: DLEqProof::<dfg::EdwardsPoint>::read(reader)? }) Ok(ClsagAddendum { key_image: xH, dleq: DLEqProof::<dfg::EdwardsPoint>::read(reader)? })

View file

@ -147,8 +147,8 @@ impl RctBase {
} }
pub fn read<R: Read>(inputs: usize, outputs: usize, r: &mut R) -> io::Result<(RctBase, RctType)> { pub fn read<R: Read>(inputs: usize, outputs: usize, r: &mut R) -> io::Result<(RctBase, RctType)> {
let rct_type = RctType::from_byte(read_byte(r)?) let rct_type =
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid RCT type"))?; RctType::from_byte(read_byte(r)?).ok_or_else(|| io::Error::other("invalid RCT type"))?;
match rct_type { match rct_type {
RctType::Null => {} RctType::Null => {}
@ -164,7 +164,7 @@ impl RctBase {
// If there are Bulletproofs, there must be a matching amount of outputs, implicitly // If there are Bulletproofs, there must be a matching amount of outputs, implicitly
// banning 0 outputs // banning 0 outputs
// Since HF 12 (CLSAG being 13), a 2-output minimum has also been enforced // Since HF 12 (CLSAG being 13), a 2-output minimum has also been enforced
Err(io::Error::new(io::ErrorKind::Other, "RCT with Bulletproofs(+) had 0 outputs"))?; Err(io::Error::other("RCT with Bulletproofs(+) had 0 outputs"))?;
} }
} }
} }
@ -273,7 +273,7 @@ impl RctPrunable {
// And then for RctNull, that's only allowed for miner TXs which require one input of // And then for RctNull, that's only allowed for miner TXs which require one input of
// Input::Gen // Input::Gen
if decoys.is_empty() { if decoys.is_empty() {
Err(io::Error::new(io::ErrorKind::Other, "transaction had no inputs"))?; Err(io::Error::other("transaction had no inputs"))?;
} }
Ok(match rct_type { Ok(match rct_type {
@ -295,7 +295,7 @@ impl RctPrunable {
read_varint(r)? read_varint(r)?
}) != 1 }) != 1
{ {
Err(io::Error::new(io::ErrorKind::Other, "n bulletproofs instead of one"))?; Err(io::Error::other("n bulletproofs instead of one"))?;
} }
Bulletproofs::read(r)? Bulletproofs::read(r)?
}, },
@ -306,7 +306,7 @@ impl RctPrunable {
RctType::Clsag | RctType::BulletproofsPlus => RctPrunable::Clsag { RctType::Clsag | RctType::BulletproofsPlus => RctPrunable::Clsag {
bulletproofs: { bulletproofs: {
if read_varint::<_, u64>(r)? != 1 { if read_varint::<_, u64>(r)? != 1 {
Err(io::Error::new(io::ErrorKind::Other, "n bulletproofs instead of one"))?; Err(io::Error::other("n bulletproofs instead of one"))?;
} }
(if rct_type == RctType::Clsag { Bulletproofs::read } else { Bulletproofs::read_plus })( (if rct_type == RctType::Clsag { Bulletproofs::read } else { Bulletproofs::read_plus })(
r, r,

View file

@ -385,7 +385,7 @@ impl<R: RpcConnection> Rpc<R> {
let mut is_okay = false; let mut is_okay = false;
if read_bytes::<_, { EPEE_HEADER.len() }>(&mut indexes)? != EPEE_HEADER { if read_bytes::<_, { EPEE_HEADER.len() }>(&mut indexes)? != EPEE_HEADER {
Err(io::Error::new(io::ErrorKind::Other, "invalid header"))?; Err(io::Error::other("invalid header"))?;
} }
let read_object = |reader: &mut &[u8]| -> io::Result<Vec<u64>> { let read_object = |reader: &mut &[u8]| -> io::Result<Vec<u64>> {
@ -401,7 +401,7 @@ impl<R: RpcConnection> Rpc<R> {
let iters = if type_with_array_flag != kind { read_epee_vi(reader)? } else { 1 }; let iters = if type_with_array_flag != kind { read_epee_vi(reader)? } else { 1 };
if (&name == b"o_indexes") && (kind != 5) { if (&name == b"o_indexes") && (kind != 5) {
Err(io::Error::new(io::ErrorKind::Other, "o_indexes weren't u64s"))?; Err(io::Error::other("o_indexes weren't u64s"))?;
} }
let f = match kind { let f = match kind {
@ -428,28 +428,19 @@ impl<R: RpcConnection> Rpc<R> {
let len = read_epee_vi(reader)?; let len = read_epee_vi(reader)?;
read_raw_vec( read_raw_vec(
read_byte, read_byte,
len len.try_into().map_err(|_| io::Error::other("u64 length exceeded usize"))?,
.try_into()
.map_err(|_| io::Error::new(io::ErrorKind::Other, "u64 length exceeded usize"))?,
reader, reader,
) )
}, },
// bool // bool
11 => |reader: &mut &[u8]| read_raw_vec(read_byte, 1, reader), 11 => |reader: &mut &[u8]| read_raw_vec(read_byte, 1, reader),
// object, errors here as it shouldn't be used on this call // object, errors here as it shouldn't be used on this call
12 => |_: &mut &[u8]| { 12 => {
Err(io::Error::new( |_: &mut &[u8]| Err(io::Error::other("node used object in reply to get_o_indexes"))
io::ErrorKind::Other,
"node used object in reply to get_o_indexes",
))
},
// array, so far unused
13 => |_: &mut &[u8]| {
Err(io::Error::new(io::ErrorKind::Other, "node used the unused array type"))
},
_ => {
|_: &mut &[u8]| Err(io::Error::new(io::ErrorKind::Other, "node used an invalid type"))
} }
// array, so far unused
13 => |_: &mut &[u8]| Err(io::Error::other("node used the unused array type")),
_ => |_: &mut &[u8]| Err(io::Error::other("node used an invalid type")),
}; };
let mut bytes_res = vec![]; let mut bytes_res = vec![];
@ -461,21 +452,23 @@ impl<R: RpcConnection> Rpc<R> {
match name.as_slice() { match name.as_slice() {
b"o_indexes" => { b"o_indexes" => {
for o_index in bytes_res { for o_index in bytes_res {
actual_res.push(u64::from_le_bytes(o_index.try_into().map_err(|_| { actual_res.push(u64::from_le_bytes(
io::Error::new(io::ErrorKind::Other, "node didn't provide 8 bytes for a u64") o_index
})?)); .try_into()
.map_err(|_| io::Error::other("node didn't provide 8 bytes for a u64"))?,
));
} }
res = Some(actual_res); res = Some(actual_res);
} }
b"status" => { b"status" => {
if bytes_res if bytes_res
.first() .first()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "status wasn't a string"))? .ok_or_else(|| io::Error::other("status wasn't a string"))?
.as_slice() != .as_slice() !=
b"OK" b"OK"
{ {
// TODO: Better handle non-OK responses // TODO: Better handle non-OK responses
Err(io::Error::new(io::ErrorKind::Other, "response wasn't OK"))?; Err(io::Error::other("response wasn't OK"))?;
} }
is_okay = true; is_okay = true;
} }
@ -490,7 +483,7 @@ impl<R: RpcConnection> Rpc<R> {
// Didn't return a response with a status // Didn't return a response with a status
// (if the status wasn't okay, we would've already errored) // (if the status wasn't okay, we would've already errored)
if !is_okay { if !is_okay {
Err(io::Error::new(io::ErrorKind::Other, "response didn't contain a status"))?; Err(io::Error::other("response didn't contain a status"))?;
} }
// If the Vec was empty, it would've been omitted, hence the unwrap_or // If the Vec was empty, it would've been omitted, hence the unwrap_or

View file

@ -100,19 +100,17 @@ pub(crate) fn read_varint<R: Read, U: sealed::VarInt>(r: &mut R) -> io::Result<U
while { while {
let b = read_byte(r)?; let b = read_byte(r)?;
if (bits != 0) && (b == 0) { if (bits != 0) && (b == 0) {
Err(io::Error::new(io::ErrorKind::Other, "non-canonical varint"))?; Err(io::Error::other("non-canonical varint"))?;
} }
if ((bits + 7) > 64) && (b >= (1 << (64 - bits))) { if ((bits + 7) > 64) && (b >= (1 << (64 - bits))) {
Err(io::Error::new(io::ErrorKind::Other, "varint overflow"))?; Err(io::Error::other("varint overflow"))?;
} }
res += u64::from(b & (!VARINT_CONTINUATION_MASK)) << bits; res += u64::from(b & (!VARINT_CONTINUATION_MASK)) << bits;
bits += 7; bits += 7;
b & VARINT_CONTINUATION_MASK == VARINT_CONTINUATION_MASK b & VARINT_CONTINUATION_MASK == VARINT_CONTINUATION_MASK
} {} } {}
res res.try_into().map_err(|_| io::Error::other("VarInt does not fit into integer type"))
.try_into()
.map_err(|_| io::Error::new(io::ErrorKind::Other, "VarInt does not fit into integer type"))
} }
// All scalar fields supported by monero-serai are checked to be canonical for valid transactions // All scalar fields supported by monero-serai are checked to be canonical for valid transactions
@ -123,7 +121,7 @@ pub(crate) fn read_varint<R: Read, U: sealed::VarInt>(r: &mut R) -> io::Result<U
// reduction applied // reduction applied
pub(crate) fn read_scalar<R: Read>(r: &mut R) -> io::Result<Scalar> { pub(crate) fn read_scalar<R: Read>(r: &mut R) -> io::Result<Scalar> {
Option::from(Scalar::from_canonical_bytes(read_bytes(r)?)) Option::from(Scalar::from_canonical_bytes(read_bytes(r)?))
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "unreduced scalar")) .ok_or_else(|| io::Error::other("unreduced scalar"))
} }
pub(crate) fn read_point<R: Read>(r: &mut R) -> io::Result<EdwardsPoint> { pub(crate) fn read_point<R: Read>(r: &mut R) -> io::Result<EdwardsPoint> {
@ -132,14 +130,14 @@ pub(crate) fn read_point<R: Read>(r: &mut R) -> io::Result<EdwardsPoint> {
.decompress() .decompress()
// Ban points which are either unreduced or -0 // Ban points which are either unreduced or -0
.filter(|point| point.compress().to_bytes() == bytes) .filter(|point| point.compress().to_bytes() == bytes)
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point")) .ok_or_else(|| io::Error::other("invalid point"))
} }
pub(crate) fn read_torsion_free_point<R: Read>(r: &mut R) -> io::Result<EdwardsPoint> { pub(crate) fn read_torsion_free_point<R: Read>(r: &mut R) -> io::Result<EdwardsPoint> {
read_point(r) read_point(r)
.ok() .ok()
.filter(EdwardsPoint::is_torsion_free) .filter(EdwardsPoint::is_torsion_free)
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point")) .ok_or_else(|| io::Error::other("invalid point"))
} }
pub(crate) fn read_raw_vec<R: Read, T, F: Fn(&mut R) -> io::Result<T>>( pub(crate) fn read_raw_vec<R: Read, T, F: Fn(&mut R) -> io::Result<T>>(

View file

@ -67,9 +67,7 @@ impl Input {
key_image: read_torsion_free_point(r)?, key_image: read_torsion_free_point(r)?,
} }
} }
_ => { _ => Err(io::Error::other("Tried to deserialize unknown/unused input type"))?,
Err(io::Error::new(io::ErrorKind::Other, "Tried to deserialize unknown/unused input type"))?
}
}) })
} }
} }
@ -109,7 +107,7 @@ impl Output {
let amount = read_varint(r)?; let amount = read_varint(r)?;
let amount = if rct { let amount = if rct {
if amount != 0 { if amount != 0 {
Err(io::Error::new(io::ErrorKind::Other, "RCT TX output wasn't 0"))?; Err(io::Error::other("RCT TX output wasn't 0"))?;
} }
None None
} else { } else {
@ -119,10 +117,7 @@ impl Output {
let view_tag = match read_byte(r)? { let view_tag = match read_byte(r)? {
2 => false, 2 => false,
3 => true, 3 => true,
_ => Err(io::Error::new( _ => Err(io::Error::other("Tried to deserialize unknown/unused output type"))?,
io::ErrorKind::Other,
"Tried to deserialize unknown/unused output type",
))?,
}; };
Ok(Output { Ok(Output {
@ -220,14 +215,14 @@ impl TransactionPrefix {
let version = read_varint(r)?; let version = read_varint(r)?;
// TODO: Create an enum out of version // TODO: Create an enum out of version
if (version == 0) || (version > 2) { if (version == 0) || (version > 2) {
Err(io::Error::new(io::ErrorKind::Other, "unrecognized transaction version"))?; Err(io::Error::other("unrecognized transaction version"))?;
} }
let timelock = Timelock::from_raw(read_varint(r)?); let timelock = Timelock::from_raw(read_varint(r)?);
let inputs = read_vec(|r| Input::read(r), r)?; let inputs = read_vec(|r| Input::read(r), r)?;
if inputs.is_empty() { if inputs.is_empty() {
Err(io::Error::new(io::ErrorKind::Other, "transaction had no inputs"))?; Err(io::Error::other("transaction had no inputs"))?;
} }
let is_miner_tx = matches!(inputs[0], Input::Gen { .. }); let is_miner_tx = matches!(inputs[0], Input::Gen { .. });
@ -310,9 +305,7 @@ impl Transaction {
.inputs .inputs
.iter() .iter()
.map(|input| match input { .map(|input| match input {
Input::Gen(..) => { Input::Gen(..) => Err(io::Error::other("Input::Gen present in non-coinbase v1 TX"))?,
Err(io::Error::new(io::ErrorKind::Other, "Input::Gen present in non-coinbase v1 TX"))?
}
// v1 TXs can burn v2 outputs // v1 TXs can burn v2 outputs
// dcff3fe4f914d6b6bd4a5b800cc4cca8f2fdd1bd73352f0700d463d36812f328 is one such TX // dcff3fe4f914d6b6bd4a5b800cc4cca8f2fdd1bd73352f0700d463d36812f328 is one such TX
// It includes a pre-RCT signature for a RCT output, yet if you interpret the RCT // It includes a pre-RCT signature for a RCT output, yet if you interpret the RCT
@ -326,16 +319,13 @@ impl Transaction {
let mut out = 0; let mut out = 0;
for output in &prefix.outputs { for output in &prefix.outputs {
if output.amount.is_none() { if output.amount.is_none() {
Err(io::Error::new(io::ErrorKind::Other, "v1 transaction had a 0-amount output"))?; Err(io::Error::other("v1 transaction had a 0-amount output"))?;
} }
out += output.amount.unwrap(); out += output.amount.unwrap();
} }
if in_amount < out { if in_amount < out {
Err(io::Error::new( Err(io::Error::other("transaction spent more than it had as inputs"))?;
io::ErrorKind::Other,
"transaction spent more than it had as inputs",
))?;
} }
rct_signatures.base.fee = in_amount - out; rct_signatures.base.fee = in_amount - out;
} }
@ -353,7 +343,7 @@ impl Transaction {
r, r,
)?; )?;
} else { } else {
Err(io::Error::new(io::ErrorKind::Other, "Tried to deserialize unknown version"))?; Err(io::Error::other("Tried to deserialize unknown version"))?;
} }
Ok(Transaction { prefix, signatures, rct_signatures }) Ok(Transaction { prefix, signatures, rct_signatures })

View file

@ -62,7 +62,7 @@ impl PaymentId {
Ok(match read_byte(r)? { Ok(match read_byte(r)? {
0 => PaymentId::Unencrypted(read_bytes(r)?), 0 => PaymentId::Unencrypted(read_bytes(r)?),
1 => PaymentId::Encrypted(read_bytes(r)?), 1 => PaymentId::Encrypted(read_bytes(r)?),
_ => Err(io::Error::new(io::ErrorKind::Other, "unknown payment ID type"))?, _ => Err(io::Error::other("unknown payment ID type"))?,
}) })
} }
} }
@ -106,13 +106,13 @@ impl ExtraField {
2 => ExtraField::Nonce({ 2 => ExtraField::Nonce({
let nonce = read_vec(read_byte, r)?; let nonce = read_vec(read_byte, r)?;
if nonce.len() > MAX_TX_EXTRA_NONCE_SIZE { if nonce.len() > MAX_TX_EXTRA_NONCE_SIZE {
Err(io::Error::new(io::ErrorKind::Other, "too long nonce"))?; Err(io::Error::other("too long nonce"))?;
} }
nonce nonce
}), }),
3 => ExtraField::MergeMining(read_varint(r)?, read_bytes(r)?), 3 => ExtraField::MergeMining(read_varint(r)?, read_bytes(r)?),
4 => ExtraField::PublicKeys(read_vec(read_point, r)?), 4 => ExtraField::PublicKeys(read_vec(read_point, r)?),
_ => Err(io::Error::new(io::ErrorKind::Other, "unknown extra field"))?, _ => Err(io::Error::other("unknown extra field"))?,
}) })
} }
} }

View file

@ -146,7 +146,7 @@ impl Metadata {
let subaddress = if read_byte(r)? == 1 { let subaddress = if read_byte(r)? == 1 {
Some( Some(
SubaddressIndex::new(read_u32(r)?, read_u32(r)?) SubaddressIndex::new(read_u32(r)?, read_u32(r)?)
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid subaddress in metadata"))?, .ok_or_else(|| io::Error::other("invalid subaddress in metadata"))?,
) )
} else { } else {
None None

View file

@ -965,7 +965,7 @@ impl Eventuality {
String::from_utf8(read_vec(read_byte, r)?) String::from_utf8(read_vec(read_byte, r)?)
.ok() .ok()
.and_then(|str| MoneroAddress::from_str_raw(&str).ok()) .and_then(|str| MoneroAddress::from_str_raw(&str).ok())
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid address")) .ok_or_else(|| io::Error::other("invalid address"))
} }
fn read_payment<R: io::Read>(r: &mut R) -> io::Result<InternalPayment> { fn read_payment<R: io::Read>(r: &mut R) -> io::Result<InternalPayment> {
@ -977,12 +977,12 @@ impl Eventuality {
view: match read_byte(r)? { view: match read_byte(r)? {
0 => None, 0 => None,
1 => Some(Zeroizing::new(read_scalar(r)?)), 1 => Some(Zeroizing::new(read_scalar(r)?)),
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid change payment"))?, _ => Err(io::Error::other("invalid change payment"))?,
}, },
}, },
read_u64(r)?, read_u64(r)?,
), ),
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid payment"))?, _ => Err(io::Error::other("invalid payment"))?,
}) })
} }

View file

@ -28,6 +28,10 @@ mod shims {
Error { kind, error: Box::new(error) } Error { kind, error: Box::new(error) }
} }
pub fn other<E: 'static + Send + Sync>(error: E) -> Error {
Error { kind: ErrorKind::Other, error: Box::new(error) }
}
pub fn kind(&self) -> ErrorKind { pub fn kind(&self) -> ErrorKind {
self.kind self.kind
} }

View file

@ -151,8 +151,8 @@ impl TributarySpec {
let mut network = [0; 1]; let mut network = [0; 1];
reader.read_exact(&mut network)?; reader.read_exact(&mut network)?;
let network = NetworkId::decode(&mut &network[..]) let network =
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid network"))?; NetworkId::decode(&mut &network[..]).map_err(|_| io::Error::other("invalid network"))?;
let mut validators_len = [0; 4]; let mut validators_len = [0; 4];
reader.read_exact(&mut validators_len)?; reader.read_exact(&mut validators_len)?;
@ -194,7 +194,7 @@ impl<Id: Clone + PartialEq + Eq + Debug + Encode + Decode> Debug for SignData<Id
impl<Id: Clone + PartialEq + Eq + Debug + Encode + Decode> ReadWrite for SignData<Id> { impl<Id: Clone + PartialEq + Eq + Debug + Encode + Decode> ReadWrite for SignData<Id> {
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> { fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let plan = Id::decode(&mut scale::IoReader(&mut *reader)) let plan = Id::decode(&mut scale::IoReader(&mut *reader))
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid plan in SignData"))?; .map_err(|_| io::Error::other("invalid plan in SignData"))?;
let mut attempt = [0; 4]; let mut attempt = [0; 4];
reader.read_exact(&mut attempt)?; reader.read_exact(&mut attempt)?;
@ -204,7 +204,7 @@ impl<Id: Clone + PartialEq + Eq + Debug + Encode + Decode> ReadWrite for SignDat
let mut data_pieces = [0]; let mut data_pieces = [0];
reader.read_exact(&mut data_pieces)?; reader.read_exact(&mut data_pieces)?;
if data_pieces[0] == 0 { if data_pieces[0] == 0 {
Err(io::Error::new(io::ErrorKind::Other, "zero pieces of data in SignData"))?; Err(io::Error::other("zero pieces of data in SignData"))?;
} }
let mut all_data = vec![]; let mut all_data = vec![];
for _ in 0 .. data_pieces[0] { for _ in 0 .. data_pieces[0] {
@ -236,7 +236,7 @@ impl<Id: Clone + PartialEq + Eq + Debug + Encode + Decode> ReadWrite for SignDat
// Monero is limited to ~120 inputs per TX // Monero is limited to ~120 inputs per TX
// //
// Bitcoin has a much higher input count of 520, yet it only uses 64 bytes per preprocess // Bitcoin has a much higher input count of 520, yet it only uses 64 bytes per preprocess
Err(io::Error::new(io::ErrorKind::Other, "signing data exceeded 65535 bytes"))?; Err(io::Error::other("signing data exceeded 65535 bytes"))?;
} }
writer.write_all(&u16::try_from(data.len()).unwrap().to_le_bytes())?; writer.write_all(&u16::try_from(data.len()).unwrap().to_le_bytes())?;
writer.write_all(data)?; writer.write_all(data)?;
@ -370,9 +370,8 @@ impl ReadWrite for Transaction {
0 => Ok(Transaction::RemoveParticipant({ 0 => Ok(Transaction::RemoveParticipant({
let mut participant = [0; 2]; let mut participant = [0; 2];
reader.read_exact(&mut participant)?; reader.read_exact(&mut participant)?;
Participant::new(u16::from_le_bytes(participant)).ok_or_else(|| { Participant::new(u16::from_le_bytes(participant))
io::Error::new(io::ErrorKind::Other, "invalid participant in RemoveParticipant") .ok_or_else(|| io::Error::other("invalid participant in RemoveParticipant"))?
})?
})), })),
1 => { 1 => {
@ -385,15 +384,14 @@ impl ReadWrite for Transaction {
reader.read_exact(&mut commitments_len)?; reader.read_exact(&mut commitments_len)?;
let commitments_len = usize::from(commitments_len[0]); let commitments_len = usize::from(commitments_len[0]);
if commitments_len == 0 { if commitments_len == 0 {
Err(io::Error::new(io::ErrorKind::Other, "zero commitments in DkgCommitments"))?; Err(io::Error::other("zero commitments in DkgCommitments"))?;
} }
let mut each_commitments_len = [0; 2]; let mut each_commitments_len = [0; 2];
reader.read_exact(&mut each_commitments_len)?; reader.read_exact(&mut each_commitments_len)?;
let each_commitments_len = usize::from(u16::from_le_bytes(each_commitments_len)); let each_commitments_len = usize::from(u16::from_le_bytes(each_commitments_len));
if (commitments_len * each_commitments_len) > TRANSACTION_SIZE_LIMIT { if (commitments_len * each_commitments_len) > TRANSACTION_SIZE_LIMIT {
Err(io::Error::new( Err(io::Error::other(
io::ErrorKind::Other,
"commitments present in transaction exceeded transaction size limit", "commitments present in transaction exceeded transaction size limit",
))?; ))?;
} }
@ -454,15 +452,13 @@ impl ReadWrite for Transaction {
let mut accuser = [0; 2]; let mut accuser = [0; 2];
reader.read_exact(&mut accuser)?; reader.read_exact(&mut accuser)?;
let accuser = Participant::new(u16::from_le_bytes(accuser)).ok_or_else(|| { let accuser = Participant::new(u16::from_le_bytes(accuser))
io::Error::new(io::ErrorKind::Other, "invalid participant in InvalidDkgShare") .ok_or_else(|| io::Error::other("invalid participant in InvalidDkgShare"))?;
})?;
let mut faulty = [0; 2]; let mut faulty = [0; 2];
reader.read_exact(&mut faulty)?; reader.read_exact(&mut faulty)?;
let faulty = Participant::new(u16::from_le_bytes(faulty)).ok_or_else(|| { let faulty = Participant::new(u16::from_le_bytes(faulty))
io::Error::new(io::ErrorKind::Other, "invalid participant in InvalidDkgShare") .ok_or_else(|| io::Error::other("invalid participant in InvalidDkgShare"))?;
})?;
let mut blame_len = [0; 2]; let mut blame_len = [0; 2];
reader.read_exact(&mut blame_len)?; reader.read_exact(&mut blame_len)?;
@ -534,7 +530,7 @@ impl ReadWrite for Transaction {
Ok(Transaction::SignCompleted { plan, tx_hash, first_signer, signature }) Ok(Transaction::SignCompleted { plan, tx_hash, first_signer, signature })
} }
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid transaction type")), _ => Err(io::Error::other("invalid transaction type")),
} }
} }
@ -549,15 +545,12 @@ impl ReadWrite for Transaction {
writer.write_all(&[1])?; writer.write_all(&[1])?;
writer.write_all(&attempt.to_le_bytes())?; writer.write_all(&attempt.to_le_bytes())?;
if commitments.is_empty() { if commitments.is_empty() {
Err(io::Error::new(io::ErrorKind::Other, "zero commitments in DkgCommitments"))? Err(io::Error::other("zero commitments in DkgCommitments"))?
} }
writer.write_all(&[u8::try_from(commitments.len()).unwrap()])?; writer.write_all(&[u8::try_from(commitments.len()).unwrap()])?;
for commitments_i in commitments { for commitments_i in commitments {
if commitments_i.len() != commitments[0].len() { if commitments_i.len() != commitments[0].len() {
Err(io::Error::new( Err(io::Error::other("commitments of differing sizes in DkgCommitments"))?
io::ErrorKind::Other,
"commitments of differing sizes in DkgCommitments",
))?
} }
} }
writer.write_all(&u16::try_from(commitments[0].len()).unwrap().to_le_bytes())?; writer.write_all(&u16::try_from(commitments[0].len()).unwrap().to_le_bytes())?;

View file

@ -81,7 +81,7 @@ impl<T: TransactionTrait> ReadWrite for Transaction<T> {
let tx = T::read(reader)?; let tx = T::read(reader)?;
Ok(Transaction::Application(tx)) Ok(Transaction::Application(tx))
} }
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid transaction type")), _ => Err(io::Error::other("invalid transaction type")),
} }
} }
fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> { fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {

View file

@ -412,7 +412,7 @@ async fn block_tx_ordering() {
match kind[0] { match kind[0] {
0 => Ok(SignedTx::Signed(Box::new(SignedTransaction::read(reader)?))), 0 => Ok(SignedTx::Signed(Box::new(SignedTransaction::read(reader)?))),
1 => Ok(SignedTx::Provided(Box::new(ProvidedTransaction::read(reader)?))), 1 => Ok(SignedTx::Provided(Box::new(ProvidedTransaction::read(reader)?))),
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid transaction type")), _ => Err(io::Error::other("invalid transaction type")),
} }
} }

View file

@ -55,7 +55,7 @@ impl ReadWrite for Signed {
reader.read_exact(&mut nonce)?; reader.read_exact(&mut nonce)?;
let nonce = u32::from_le_bytes(nonce); let nonce = u32::from_le_bytes(nonce);
if nonce >= (u32::MAX - 1) { if nonce >= (u32::MAX - 1) {
Err(io::Error::new(io::ErrorKind::Other, "nonce exceeded limit"))?; Err(io::Error::other("nonce exceeded limit"))?;
} }
let mut signature = SchnorrSignature::<Ristretto>::read(reader)?; let mut signature = SchnorrSignature::<Ristretto>::read(reader)?;
@ -64,7 +64,7 @@ impl ReadWrite for Signed {
// We should never produce zero signatures though meaning this should never come up // We should never produce zero signatures though meaning this should never come up
// If it does somehow come up, this is a decent courtesy // If it does somehow come up, this is a decent courtesy
signature.zeroize(); signature.zeroize();
Err(io::Error::new(io::ErrorKind::Other, "signature nonce was identity"))?; Err(io::Error::other("signature nonce was identity"))?;
} }
Ok(Signed { signer, nonce, signature }) Ok(Signed { signer, nonce, signature })
@ -73,7 +73,7 @@ impl ReadWrite for Signed {
fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> { fn write<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
// This is either an invalid signature or a private key leak // This is either an invalid signature or a private key leak
if self.signature.R.is_identity().into() { if self.signature.R.is_identity().into() {
Err(io::Error::new(io::ErrorKind::Other, "signature nonce was identity"))?; Err(io::Error::other("signature nonce was identity"))?;
} }
writer.write_all(&self.signer.to_bytes())?; writer.write_all(&self.signer.to_bytes())?;
writer.write_all(&self.nonce.to_le_bytes())?; writer.write_all(&self.nonce.to_le_bytes())?;

View file

@ -93,7 +93,7 @@ pub trait Ciphersuite:
// ff mandates this is canonical // ff mandates this is canonical
let res = Option::<Self::F>::from(Self::F::from_repr(encoding)) let res = Option::<Self::F>::from(Self::F::from_repr(encoding))
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "non-canonical scalar")); .ok_or_else(|| io::Error::other("non-canonical scalar"));
encoding.as_mut().zeroize(); encoding.as_mut().zeroize();
res res
} }
@ -106,9 +106,9 @@ pub trait Ciphersuite:
reader.read_exact(encoding.as_mut())?; reader.read_exact(encoding.as_mut())?;
let point = Option::<Self::G>::from(Self::G::from_bytes(&encoding)) let point = Option::<Self::G>::from(Self::G::from_bytes(&encoding))
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "invalid point"))?; .ok_or_else(|| io::Error::other("invalid point"))?;
if point.to_bytes().as_ref() != encoding.as_ref() { if point.to_bytes().as_ref() != encoding.as_ref() {
Err(io::Error::new(io::ErrorKind::Other, "non-canonical point"))?; Err(io::Error::other("non-canonical point"))?;
} }
Ok(point) Ok(point)
} }

View file

@ -306,8 +306,7 @@ mod lib {
/// Read keys from a type satisfying std::io::Read. /// Read keys from a type satisfying std::io::Read.
pub fn read<R: io::Read>(reader: &mut R) -> io::Result<ThresholdCore<C>> { pub fn read<R: io::Read>(reader: &mut R) -> io::Result<ThresholdCore<C>> {
{ {
let different = let different = || io::Error::other("deserializing ThresholdCore for another curve");
|| io::Error::new(io::ErrorKind::Other, "deserializing ThresholdCore for another curve");
let mut id_len = [0; 4]; let mut id_len = [0; 4];
reader.read_exact(&mut id_len)?; reader.read_exact(&mut id_len)?;
@ -331,8 +330,7 @@ mod lib {
( (
read_u16()?, read_u16()?,
read_u16()?, read_u16()?,
Participant::new(read_u16()?) Participant::new(read_u16()?).ok_or(io::Error::other("invalid participant index"))?,
.ok_or(io::Error::new(io::ErrorKind::Other, "invalid participant index"))?,
) )
}; };
@ -344,8 +342,7 @@ mod lib {
} }
Ok(ThresholdCore::new( Ok(ThresholdCore::new(
ThresholdParams::new(t, n, i) ThresholdParams::new(t, n, i).map_err(|_| io::Error::other("invalid parameters"))?,
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid parameters"))?,
secret_share, secret_share,
verification_shares, verification_shares,
)) ))

View file

@ -55,11 +55,9 @@ pub(crate) fn read_point<R: Read, G: PrimeGroup>(r: &mut R) -> io::Result<G> {
let mut repr = G::Repr::default(); let mut repr = G::Repr::default();
r.read_exact(repr.as_mut())?; r.read_exact(repr.as_mut())?;
let point = G::from_bytes(&repr); let point = G::from_bytes(&repr);
let Some(point) = Option::<G>::from(point) else { let Some(point) = Option::<G>::from(point) else { Err(io::Error::other("invalid point"))? };
Err(io::Error::new(io::ErrorKind::Other, "invalid point"))?
};
if point.to_bytes().as_ref() != repr.as_ref() { if point.to_bytes().as_ref() != repr.as_ref() {
Err(io::Error::new(io::ErrorKind::Other, "non-canonical point"))?; Err(io::Error::other("non-canonical point"))?;
} }
Ok(point) Ok(point)
} }

View file

@ -14,7 +14,7 @@ use ff::{Field, PrimeField};
use group::prime::PrimeGroup; use group::prime::PrimeGroup;
#[cfg(feature = "serialize")] #[cfg(feature = "serialize")]
use std::io::{self, ErrorKind, Error, Read, Write}; use std::io::{self, Error, Read, Write};
/// A cross-group DLEq proof capable of proving that two public keys, across two different curves, /// A cross-group DLEq proof capable of proving that two public keys, across two different curves,
/// share a private key. /// share a private key.
@ -91,7 +91,7 @@ fn read_scalar<R: Read, F: PrimeField>(r: &mut R) -> io::Result<F> {
r.read_exact(repr.as_mut())?; r.read_exact(repr.as_mut())?;
let scalar = F::from_repr(repr); let scalar = F::from_repr(repr);
if scalar.is_none().into() { if scalar.is_none().into() {
Err(Error::new(ErrorKind::Other, "invalid scalar"))?; Err(Error::other("invalid scalar"))?;
} }
Ok(scalar.unwrap()) Ok(scalar.unwrap())
} }

View file

@ -125,7 +125,7 @@ pub trait Curve: Ciphersuite {
fn read_G<R: Read>(reader: &mut R) -> io::Result<Self::G> { fn read_G<R: Read>(reader: &mut R) -> io::Result<Self::G> {
let res = <Self as Ciphersuite>::read_G(reader)?; let res = <Self as Ciphersuite>::read_G(reader)?;
if res.is_identity().into() { if res.is_identity().into() {
Err(io::Error::new(io::ErrorKind::Other, "identity point"))?; Err(io::Error::other("identity point"))?;
} }
Ok(res) Ok(res)
} }

View file

@ -223,7 +223,7 @@ impl<C: Curve> Commitments<C> {
let dleq = MultiDLEqProof::read(reader, dleq_generators.len())?; let dleq = MultiDLEqProof::read(reader, dleq_generators.len())?;
dleq dleq
.verify(&mut dleq_transcript::<T>(context), &dleq_generators, &dleq_nonces) .verify(&mut dleq_transcript::<T>(context), &dleq_generators, &dleq_nonces)
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid DLEq proof"))?; .map_err(|_| io::Error::other("invalid DLEq proof"))?;
Some(dleq) Some(dleq)
} else { } else {
None None

View file

@ -184,8 +184,7 @@ impl TransactionTrait<Bitcoin> for Transaction {
buf buf
} }
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> { fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
Transaction::consensus_decode(reader) Transaction::consensus_decode(reader).map_err(|e| io::Error::other(format!("{e}")))
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))
} }
#[cfg(test)] #[cfg(test)]
@ -223,12 +222,10 @@ impl EventualityTrait for Eventuality {
} }
fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> { fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let plan_binding_input = OutPoint::consensus_decode(reader).map_err(|_| { let plan_binding_input = OutPoint::consensus_decode(reader)
io::Error::new(io::ErrorKind::Other, "couldn't decode outpoint in eventuality") .map_err(|_| io::Error::other("couldn't decode outpoint in eventuality"))?;
})?; let outputs = Vec::<TxOut>::consensus_decode(reader)
let outputs = Vec::<TxOut>::consensus_decode(reader).map_err(|_| { .map_err(|_| io::Error::other("couldn't decode outputs in eventuality"))?;
io::Error::new(io::ErrorKind::Other, "couldn't decode outputs in eventuality")
})?;
Ok(Eventuality { plan_binding_input, outputs }) Ok(Eventuality { plan_binding_input, outputs })
} }
fn serialize(&self) -> Vec<u8> { fn serialize(&self) -> Vec<u8> {

View file

@ -94,7 +94,7 @@ impl OutputType {
1 => OutputType::Branch, 1 => OutputType::Branch,
2 => OutputType::Change, 2 => OutputType::Change,
3 => OutputType::Forwarded, 3 => OutputType::Forwarded,
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid OutputType"))?, _ => Err(io::Error::other("invalid OutputType"))?,
}) })
} }
} }

View file

@ -34,7 +34,7 @@ impl<N: Network> Payment<N> {
.address .address
.clone() .clone()
.try_into() .try_into()
.map_err(|_| io::Error::new(io::ErrorKind::Other, "address couldn't be serialized"))?; .map_err(|_| io::Error::other("address couldn't be serialized"))?;
writer.write_all(&u32::try_from(address.len()).unwrap().to_le_bytes())?; writer.write_all(&u32::try_from(address.len()).unwrap().to_le_bytes())?;
writer.write_all(&address)?; writer.write_all(&address)?;
@ -52,8 +52,7 @@ impl<N: Network> Payment<N> {
reader.read_exact(&mut buf)?; reader.read_exact(&mut buf)?;
let mut address = vec![0; usize::try_from(u32::from_le_bytes(buf)).unwrap()]; let mut address = vec![0; usize::try_from(u32::from_le_bytes(buf)).unwrap()];
reader.read_exact(&mut address)?; reader.read_exact(&mut address)?;
let address = N::Address::try_from(address) let address = N::Address::try_from(address).map_err(|_| io::Error::other("invalid address"))?;
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid address"))?;
let mut buf = [0; 1]; let mut buf = [0; 1];
reader.read_exact(&mut buf)?; reader.read_exact(&mut buf)?;
@ -68,7 +67,7 @@ impl<N: Network> Payment<N> {
}; };
let balance = Balance::decode(&mut scale::IoReader(reader)) let balance = Balance::decode(&mut scale::IoReader(reader))
.map_err(|_| io::Error::new(io::ErrorKind::Other, "invalid balance"))?; .map_err(|_| io::Error::other("invalid balance"))?;
Ok(Payment { address, data, balance }) Ok(Payment { address, data, balance })
} }
@ -152,13 +151,10 @@ impl<N: Network> Plan<N> {
// TODO: Have Plan construction fail if change cannot be serialized // TODO: Have Plan construction fail if change cannot be serialized
let change = if let Some(change) = &self.change { let change = if let Some(change) = &self.change {
change.clone().try_into().map_err(|_| { change.clone().try_into().map_err(|_| {
io::Error::new( io::Error::other(format!(
io::ErrorKind::Other, "an address we said to use as change couldn't be convered to a Vec<u8>: {}",
format!( change.to_string(),
"an address we said to use as change couldn't be convered to a Vec<u8>: {}", ))
change.to_string(),
),
)
})? })?
} else { } else {
vec![] vec![]
@ -188,16 +184,14 @@ impl<N: Network> Plan<N> {
reader.read_exact(&mut len)?; reader.read_exact(&mut len)?;
let mut change = vec![0; usize::from(len[0])]; let mut change = vec![0; usize::from(len[0])];
reader.read_exact(&mut change)?; reader.read_exact(&mut change)?;
let change = if change.is_empty() { let change =
None if change.is_empty() {
} else { None
Some(N::Address::try_from(change).map_err(|_| { } else {
io::Error::new( Some(N::Address::try_from(change).map_err(|_| {
io::ErrorKind::Other, io::Error::other("couldn't deserialize an Address serialized into a Plan")
"couldn't deserialize an Address serialized into a Plan", })?)
) };
})?)
};
Ok(Plan { key, inputs, payments, change }) Ok(Plan { key, inputs, payments, change })
} }