extern crate alloc;
use alloc::vec::Vec;
const MARKER_OFFSET: usize = 4;
const FLAG_OFFSET: usize = 5;
const MARKER_FLAG_LEN: usize = 2;
const WITNESS_COUNT_LEN: usize = 1;
const WITNESS_LEN_LEN: usize = 1;
const WITNESS_DATA_LEN: usize = 32;
const LOCKTIME_LEN: usize = 4;
#[derive(Debug)]
pub enum StripBip141Error {
FailedToDeserializeCoinbaseVersion,
FailedToDeserializeCoinbaseInputs,
FailedToDeserializeCoinbaseOutputs,
FailedToDeserializeCoinbaseLockTime,
}
#[allow(clippy::type_complexity)]
pub fn try_strip_bip141(
coinbase_tx_prefix: &[u8],
coinbase_tx_suffix: &[u8],
) -> Result<Option<(Vec<u8>, Vec<u8>)>, StripBip141Error> {
let has_bip141_marker_and_flag =
(coinbase_tx_prefix[MARKER_OFFSET] == 0x00) && (coinbase_tx_prefix[FLAG_OFFSET] != 0x00);
if !has_bip141_marker_and_flag {
return Ok(None);
}
let mut coinbase_tx_prefix_stripped_bip141 = coinbase_tx_prefix[0..MARKER_OFFSET].to_vec();
coinbase_tx_prefix_stripped_bip141
.extend_from_slice(&coinbase_tx_prefix[MARKER_OFFSET + MARKER_FLAG_LEN..]);
let locktime_position = coinbase_tx_suffix.len() - LOCKTIME_LEN;
let mut coinbase_tx_suffix_stripped_bip141 = coinbase_tx_suffix
[..locktime_position - WITNESS_COUNT_LEN - WITNESS_LEN_LEN - WITNESS_DATA_LEN]
.to_vec();
coinbase_tx_suffix_stripped_bip141.extend_from_slice(&coinbase_tx_suffix[locktime_position..]);
Ok(Some((
coinbase_tx_prefix_stripped_bip141,
coinbase_tx_suffix_stripped_bip141,
)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_try_strip_bip141_sri_stripped() {
let coinbase_tx_prefix = [
2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 60, 2, 69, 8, 0, 22, 47, 83, 116, 114, 97,
116, 117, 109, 32, 86, 50, 32, 83, 82, 73, 32, 80, 111, 111, 108, 47, 47, 32,
]
.to_vec();
let coinbase_tx_suffix = [
254, 255, 255, 255, 2, 0, 242, 5, 42, 1, 0, 0, 0, 22, 0, 20, 235, 225, 183, 220, 194,
147, 204, 170, 14, 231, 67, 168, 111, 137, 223, 130, 88, 194, 8, 252, 0, 0, 0, 0, 0, 0,
0, 0, 38, 106, 36, 170, 33, 169, 237, 226, 246, 28, 63, 113, 209, 222, 253, 63, 169,
153, 223, 163, 105, 83, 117, 92, 105, 6, 137, 121, 153, 98, 180, 139, 235, 216, 54,
151, 78, 140, 249, 68, 8, 0, 0,
]
.to_vec();
let result = try_strip_bip141(&coinbase_tx_prefix, &coinbase_tx_suffix)
.expect("failed trying to strip bip141");
assert!(result.is_none());
}
#[test]
fn test_try_strip_bip141_braiins() {
let coinbase_tx_prefix = [
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 76, 3, 206, 226, 13, 15, 47, 115, 108, 117,
115, 104, 47, 183, 0, 23, 4, 15, 174, 96, 163, 250, 190, 109, 109, 207, 170, 255, 170,
165, 167, 227, 112, 68, 27, 6, 55, 218, 219, 107, 176, 134, 175, 81, 46, 136, 141, 22,
52, 201, 113, 254, 3, 148, 98, 86, 129, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 146, 162, 70, 0,
]
.to_vec();
let coinbase_tx_suffix = [
255, 255, 255, 255, 3, 194, 35, 192, 18, 0, 0, 0, 0, 23, 169, 20, 31, 12, 187, 236,
139, 196, 201, 69, 228, 225, 98, 73, 177, 30, 238, 145, 30, 222, 213, 95, 135, 0, 0, 0,
0, 0, 0, 0, 0, 38, 106, 36, 170, 33, 169, 237, 255, 27, 83, 239, 4, 153, 53, 158, 142,
142, 137, 160, 34, 151, 40, 92, 185, 56, 40, 203, 144, 158, 95, 20, 155, 139, 53, 163,
229, 145, 31, 81, 0, 0, 0, 0, 0, 0, 0, 0, 43, 106, 41, 82, 83, 75, 66, 76, 79, 67, 75,
58, 188, 174, 124, 112, 138, 29, 26, 158, 194, 209, 140, 216, 148, 128, 27, 238, 106,
189, 119, 214, 62, 100, 213, 246, 143, 66, 110, 12, 0, 120, 89, 116, 0, 0, 0, 0,
]
.to_vec();
let result = try_strip_bip141(&coinbase_tx_prefix, &coinbase_tx_suffix)
.expect("failed trying to strip bip141");
assert!(result.is_none());
}
#[test]
fn test_try_strip_bip141_sri_not_yet_stripped() {
let coinbase_tx_prefix = [
2, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 60, 2, 69, 8, 0, 22, 47, 83, 116,
114, 97, 116, 117, 109, 32, 86, 50, 32, 83, 82, 73, 32, 80, 111, 111, 108, 47, 47, 32,
]
.to_vec();
let coinbase_tx_suffix = [
254, 255, 255, 255, 2, 0, 242, 5, 42, 1, 0, 0, 0, 22, 0, 20, 235, 225, 183, 220, 194,
147, 204, 170, 14, 231, 67, 168, 111, 137, 223, 130, 88, 194, 8, 252, 0, 0, 0, 0, 0, 0,
0, 0, 38, 106, 36, 170, 33, 169, 237, 226, 246, 28, 63, 113, 209, 222, 253, 63, 169,
153, 223, 163, 105, 83, 117, 92, 105, 6, 137, 121, 153, 98, 180, 139, 235, 216, 54,
151, 78, 140, 249, 1, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 8, 0, 0,
]
.to_vec();
let (coinbase_tx_prefix_stripped_bip141, coinbase_tx_suffix_stripped_bip141) =
try_strip_bip141(&coinbase_tx_prefix, &coinbase_tx_suffix)
.expect("failed trying to strip bip141")
.unwrap();
assert_eq!(
coinbase_tx_prefix_stripped_bip141,
[
2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 60, 2, 69, 8, 0, 22, 47, 83, 116,
114, 97, 116, 117, 109, 32, 86, 50, 32, 83, 82, 73, 32, 80, 111, 111, 108, 47, 47,
32
]
.to_vec()
);
assert_eq!(
coinbase_tx_suffix_stripped_bip141,
[
254, 255, 255, 255, 2, 0, 242, 5, 42, 1, 0, 0, 0, 22, 0, 20, 235, 225, 183, 220,
194, 147, 204, 170, 14, 231, 67, 168, 111, 137, 223, 130, 88, 194, 8, 252, 0, 0, 0,
0, 0, 0, 0, 0, 38, 106, 36, 170, 33, 169, 237, 226, 246, 28, 63, 113, 209, 222,
253, 63, 169, 153, 223, 163, 105, 83, 117, 92, 105, 6, 137, 121, 153, 98, 180, 139,
235, 216, 54, 151, 78, 140, 249, 68, 8, 0, 0
]
.to_vec()
);
}
}