use core::num::NonZero;
use crate::{
io::VarInt,
ed25519::CompressedPoint,
extra::{ARBITRARY_DATA_MARKER, MAX_EXTRA_SIZE_BY_RELAY_RULE, ExtraField, Extra},
};
const MAX_TX_EXTRA_PADDING_COUNT: u8 = 255;
#[rustfmt::skip]
const _RUSTFMT_SKIP: () = ();
const PUB_KEY_BYTES: [u8; 33] = [
1, 30, 208, 98, 162, 133, 64, 85, 83, 112, 91, 188, 89, 211, 24, 131, 39, 154, 22, 228, 80, 63,
198, 141, 173, 111, 244, 183, 4, 149, 186, 140, 230,
];
fn pub_key() -> CompressedPoint {
CompressedPoint::from(<[u8; 32]>::try_from(&PUB_KEY_BYTES[1 .. PUB_KEY_BYTES.len()]).unwrap())
}
fn test_write_buf(extra: &Extra, buf: &[u8]) {
let mut w: Vec<u8> = vec![];
Extra::write(extra, &mut w).unwrap();
assert_eq!(buf, w);
}
#[test]
fn empty_extra() {
let buf: Vec<u8> = vec![];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert!(extra.0.is_empty());
test_write_buf(&extra, &buf);
}
#[test]
fn padding_only_size_1() {
let buf: Vec<u8> = vec![0];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::Padding(NonZero::new(1).unwrap())]);
test_write_buf(&extra, &buf);
}
#[test]
fn padding_only_size_2() {
let buf: Vec<u8> = vec![0, 0];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::Padding(NonZero::new(2).unwrap())]);
test_write_buf(&extra, &buf);
}
#[test]
fn padding_only_max_size() {
let buf: Vec<u8> = vec![0; usize::from(MAX_TX_EXTRA_PADDING_COUNT)];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::Padding(NonZero::new(MAX_TX_EXTRA_PADDING_COUNT).unwrap())]);
test_write_buf(&extra, &buf);
}
#[test]
fn padding_only_exceed_max_size() {
let buf: Vec<u8> = vec![0; usize::from(MAX_TX_EXTRA_PADDING_COUNT) + 1];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert!(extra.0.is_empty());
}
#[test]
fn invalid_padding_only() {
let buf: Vec<u8> = vec![0, 42];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert!(extra.0.is_empty());
}
#[test]
fn pub_key_only() {
let buf: Vec<u8> = PUB_KEY_BYTES.to_vec();
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::PublicKey(pub_key())]);
test_write_buf(&extra, &buf);
}
#[test]
fn extra_nonce_only() {
let buf: Vec<u8> = vec![2, 1, 42];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::Nonce(vec![42])]);
test_write_buf(&extra, &buf);
}
#[test]
fn extra_nonce_only_wrong_size() {
let mut buf: Vec<u8> = vec![0; 20];
buf[0] = 2;
buf[1] = 255;
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert!(extra.0.is_empty());
}
#[test]
fn pub_key_and_padding() {
let mut buf: Vec<u8> = PUB_KEY_BYTES.to_vec();
buf.extend([
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,
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,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]);
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(
extra.0,
vec![ExtraField::PublicKey(pub_key()), ExtraField::Padding(NonZero::new(76).unwrap())]
);
test_write_buf(&extra, &buf);
}
#[test]
fn pub_key_and_invalid_padding() {
let mut buf: Vec<u8> = PUB_KEY_BYTES.to_vec();
buf.extend([0, 1]);
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::PublicKey(pub_key())]);
}
#[test]
fn extra_mysterious_minergate_only() {
let buf: Vec<u8> = vec![222, 1, 42];
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::MysteriousMinergate(vec![42])]);
test_write_buf(&extra, &buf);
}
#[test]
fn extra_mysterious_minergate_only_large() {
let mut buf: Vec<u8> = vec![222];
VarInt::write(&512u64, &mut buf).unwrap();
buf.extend_from_slice(&vec![0; 512]);
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(extra.0, vec![ExtraField::MysteriousMinergate(vec![0; 512])]);
test_write_buf(&extra, &buf);
}
#[test]
fn extra_mysterious_minergate_only_wrong_size() {
let mut buf: Vec<u8> = vec![0; 20];
buf[0] = 222;
buf[1] = 255;
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert!(extra.0.is_empty());
}
#[test]
fn extra_mysterious_minergate_and_pub_key() {
let buf = [PUB_KEY_BYTES.as_slice(), &[222, 1, 42]].concat();
let extra = Extra::read(&mut buf.as_slice()).unwrap();
assert_eq!(
extra.0,
vec![ExtraField::PublicKey(pub_key()), ExtraField::MysteriousMinergate(vec![42])]
);
test_write_buf(&extra, &buf);
}
#[test]
fn fetching_data_does_not_panic() {
assert!(Extra::read(&mut [0x02, 0x00].as_slice()).unwrap().arbitrary_data().is_empty());
assert_eq!(
Extra::read(&mut [0x02, 0x01, 0x7F].as_slice()).unwrap().arbitrary_data(),
vec![Vec::<u8>::new()]
);
}
#[test]
fn fetching_long_data_does_not_panic() {
let mut extra = Extra::new(CompressedPoint::IDENTITY, vec![]);
let mut arb_data = vec![0; 200];
arb_data[0] = ARBITRARY_DATA_MARKER;
for _ in 0 .. 5 {
extra.push_nonce(arb_data.clone());
}
assert!(extra.serialize().len() < MAX_EXTRA_SIZE_BY_RELAY_RULE);
extra.push_nonce(arb_data.clone());
assert!(extra.serialize().len() > MAX_EXTRA_SIZE_BY_RELAY_RULE);
assert_eq!(Extra::read(&mut extra.serialize().as_slice()).unwrap(), extra);
assert_eq!(extra.arbitrary_data().len(), 5);
}