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
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()) })