use bee_message::prelude::*;
use bee_test::rand::{
bytes::rand_bytes_32,
payload::{rand_indexation_payload, rand_treasury_transaction_payload},
};
const TRANSACTION_ID: &str = "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649";
const ED25519_ADDRESS_1: &str = "d56da1eb7726ed482dfe9d457cf548c2ae2a6ce3e053dbf82f11223be476adb9";
const ED25519_ADDRESS_2: &str = "efda4275375ac3675abff85235fd25a1522a2044cc6027a31b310857246f18c0";
#[test]
fn kind() {
assert_eq!(RegularEssence::KIND, 0);
}
#[test]
fn build_valid() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input1 = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let input2 = Input::Utxo(UtxoInput::new(txid, 1).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input1, input2])
.with_outputs(vec![output])
.finish();
assert!(essence.is_ok());
}
#[test]
fn build_valid_with_payload() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input1 = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let input2 = Input::Utxo(UtxoInput::new(txid, 1).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let payload = Payload::from(rand_indexation_payload());
let essence = RegularEssence::builder()
.with_inputs(vec![input1, input2])
.with_outputs(vec![output])
.with_payload(payload)
.finish();
assert!(essence.is_ok());
}
#[test]
fn build_valid_add_inputs_outputs() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input1 = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let input2 = Input::Utxo(UtxoInput::new(txid, 1).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.add_input(input1)
.add_input(input2)
.add_output(output)
.finish();
assert!(essence.is_ok());
}
#[test]
fn build_invalid_payload_kind() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input1 = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let input2 = Input::Utxo(UtxoInput::new(txid, 1).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let payload = rand_treasury_transaction_payload();
let essence = RegularEssence::builder()
.with_inputs(vec![input1, input2])
.with_outputs(vec![output])
.with_payload(payload)
.finish();
assert!(matches!(essence, Err(Error::InvalidPayloadKind(4))));
}
#[test]
fn build_invalid_input_count_low() {
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder().with_outputs(vec![output]).finish();
assert!(matches!(essence, Err(Error::InvalidInputOutputCount(0))));
}
#[test]
fn build_invalid_input_count_high() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input; 128])
.with_outputs(vec![output])
.finish();
assert!(matches!(essence, Err(Error::InvalidInputOutputCount(128))));
}
#[test]
fn build_invalid_output_count_low() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![])
.finish();
assert!(matches!(essence, Err(Error::InvalidInputOutputCount(0))));
}
#[test]
fn build_invalid_output_count_high() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output; 128])
.finish();
assert!(matches!(essence, Err(Error::InvalidInputOutputCount(128))));
}
#[test]
fn build_invalid_duplicate_utxo() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input; 2])
.with_outputs(vec![output])
.finish();
assert!(matches!(essence, Err(Error::DuplicateUtxo(_))));
}
#[test]
fn build_invalid_input_kind() {
let input = Input::Treasury(TreasuryInput::new(MilestoneId::new(rand_bytes_32())));
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output])
.finish();
assert!(matches!(essence, Err(Error::InvalidInputKind(1))));
}
#[test]
fn build_invalid_output_kind() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let amount = 1_000_000;
let output = Output::Treasury(TreasuryOutput::new(amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output])
.finish();
assert!(matches!(essence, Err(Error::InvalidOutputKind(2))));
}
#[test]
fn build_transaction_inputs_not_sorted() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input1 = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let input2 = Input::Utxo(UtxoInput::new(txid, 1).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input2, input1])
.with_outputs(vec![output])
.finish();
assert!(matches!(essence, Err(Error::TransactionInputsNotSorted)));
}
#[test]
fn build_transaction_outputs_not_sorted() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let amount = 1_000_000;
let bytes1: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address1 = Address::from(Ed25519Address::new(bytes1));
let output1 = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address1, amount).unwrap());
let bytes2: [u8; 32] = hex::decode(ED25519_ADDRESS_2).unwrap().try_into().unwrap();
let address2 = Address::from(Ed25519Address::new(bytes2));
let output2 = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address2, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output2, output1])
.finish();
assert!(matches!(essence, Err(Error::TransactionOutputsNotSorted)));
}
#[test]
fn build_single_output_duplicate_address() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let amount = 1_000_000;
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let output = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output; 2])
.finish();
assert!(matches!(essence, Err(Error::DuplicateAddress(_))));
}
#[test]
fn build_dust_allowance_output_duplicate_address() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let amount = 1_000_000;
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let output =
Output::SignatureLockedDustAllowance(SignatureLockedDustAllowanceOutput::new(address, amount).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output; 2])
.finish();
assert!(matches!(essence, Err(Error::DuplicateAddress(_))));
}
#[test]
fn build_invalid_accumulated_output() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let bytes1: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address1 = Address::from(Ed25519Address::new(bytes1));
let amount1 = IOTA_SUPPLY - 1_000_000;
let output1 = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address1, amount1).unwrap());
let bytes2: [u8; 32] = hex::decode(ED25519_ADDRESS_2).unwrap().try_into().unwrap();
let address2 = Address::from(Ed25519Address::new(bytes2));
let amount2 = 2_000_000;
let output2 = Output::SignatureLockedSingle(SignatureLockedSingleOutput::new(address2, amount2).unwrap());
let essence = RegularEssence::builder()
.with_inputs(vec![input])
.with_outputs(vec![output1, output2])
.finish();
assert!(matches!(essence, Err(Error::InvalidAccumulatedOutput(_))));
}
#[test]
fn getters() {
let txid = TransactionId::new(hex::decode(TRANSACTION_ID).unwrap().try_into().unwrap());
let input1 = Input::Utxo(UtxoInput::new(txid, 0).unwrap());
let input2 = Input::Utxo(UtxoInput::new(txid, 1).unwrap());
let bytes: [u8; 32] = hex::decode(ED25519_ADDRESS_1).unwrap().try_into().unwrap();
let address = Address::from(Ed25519Address::new(bytes));
let amount = 1_000_000;
let outputs = vec![Output::SignatureLockedSingle(
SignatureLockedSingleOutput::new(address, amount).unwrap(),
)];
let payload = Payload::from(rand_indexation_payload());
let essence = RegularEssence::builder()
.with_inputs(vec![input1, input2])
.with_outputs(outputs.clone())
.with_payload(payload.clone())
.finish()
.unwrap();
assert_eq!(essence.outputs(), outputs.as_slice());
assert_eq!(*essence.payload().as_ref().unwrap(), payload);
}