Ensure InInstruction data is properly limited

Bitcoin didn't check, assuming data was <= 80 bytes thanks to being in
OP_RETURN. An additional global check has been added.
This commit is contained in:
Luke Parker 2023-03-25 01:36:28 -04:00
parent 6a981dae6e
commit d954e67238
No known key found for this signature in database
4 changed files with 20 additions and 8 deletions

View file

@ -36,7 +36,7 @@ use bitcoin_serai::bitcoin::{
PackedLockTime, Sequence, Script, Witness, TxIn, TxOut, Address as BAddress,
};
use serai_client::coins::bitcoin::Address;
use serai_client::{primitives::MAX_DATA_LEN, coins::bitcoin::Address};
use crate::{
coins::{
@ -357,6 +357,7 @@ impl Coin for Bitcoin {
} else {
vec![]
};
data.truncate(MAX_DATA_LEN.try_into().unwrap());
outputs.push(Output { kind, output, data })
}

View file

@ -19,7 +19,7 @@ use tokio::time::sleep;
use scale::Decode;
use serai_client::{
primitives::{Amount, WithAmount},
primitives::{MAX_DATA_LEN, Amount, WithAmount},
tokens::primitives::OutInstruction,
in_instructions::primitives::{Shorthand, RefundableInInstruction},
};
@ -425,7 +425,17 @@ async fn run<C: Coin, D: Db, Co: Coordinator>(raw_db: D, coin: C, mut coordinato
return None;
}
let shorthand = Shorthand::decode(&mut output.data()).ok()?;
let data = output.data();
if data.len() > MAX_DATA_LEN {
error!(
"data in output {} exceeded MAX_DATA_LEN ({MAX_DATA_LEN}): {}",
hex::encode(output.id()),
data.len(),
);
data = data[.. MAX_DATA_LEN];
}
let shorthand = Shorthand::decode(&mut data).ok()?;
let instruction = RefundableInInstruction::try_from(shorthand).ok()?;
// TODO2: Set instruction.origin if not set (and handle refunds in general)
Some(WithAmount { data: instruction.instruction, amount: Amount(output.amount()) })

View file

@ -53,8 +53,8 @@ impl TryFrom<Vec<u8>> for Address {
EncodedAddress::P2WSH(hash) => {
Payload::WitnessProgram { version: WitnessVersion::V0, program: hash.to_vec() }
}
EncodedAddress::P2TR(hash) => {
Payload::WitnessProgram { version: WitnessVersion::V1, program: hash.to_vec() }
EncodedAddress::P2TR(key) => {
Payload::WitnessProgram { version: WitnessVersion::V1, program: key.to_vec() }
}
},
}))

View file

@ -27,9 +27,10 @@ pub use balance::*;
mod account;
pub use account::*;
// Monero, our current longest address candidate, has a longest address of featured with payment ID
// 1 (enum) + 1 (flags) + 64 (two keys) + 8 (payment ID) = 74
pub const MAX_ADDRESS_LEN: u32 = 74;
// Monero, our current longest address candidate, has a longest address of featured
// 1 (enum) + 1 (flags) + 64 (two keys) = 66
// When JAMTIS arrives, it'll become 114 bytes
pub const MAX_ADDRESS_LEN: u32 = 128;
#[derive(Clone, PartialEq, Eq, Debug, Encode, Decode, MaxEncodedLen, TypeInfo)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]