feat(applying): implement Alonzo phase-1 validations (#380)
This commit is contained in:
parent
0b1e5f0231
commit
da3e636759
33 changed files with 4900 additions and 704 deletions
|
|
@ -6,7 +6,7 @@ Starting at the root of the repository, simply go to *pallas-applying* and run `
|
|||
|
||||
## Explanations
|
||||
### Byron
|
||||
*pallas-applying/tests/byron.rs* contains multiple unit tests for validation on the Byron era.
|
||||
*pallas-applying/tests/byron.rs* contains multiple unit tests for validation in the Byron era.
|
||||
|
||||
The first one, **suceessful_mainnet_tx**, is a positive unit test. It takes the CBOR of a mainnet transaction. Namely, the one whose hash is `a06e5a0150e09f8983be2deafab9e04afc60d92e7110999eb672c903343f1e26`, which can be viewed on Cardano Explorer [here](https://cexplorer.io/tx/a06e5a0150e09f8983be2deafab9e04afc60d92e7110999eb672c903343f1e26). Such a transaction has a single input which is added to the UTxO, prior to validation, by associating it to a transaction output sitting at its real (mainnet) address. This information was taken from Cardano Explorer as well, following the address link of the only input to the transaction, and taking its raw address CBOR content.
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ Then comes a series of negative unit tests, namely:
|
|||
- **wrong_signature** takes the mainnet transaction, alters the content of its witness, and calls validation on it.
|
||||
|
||||
### ShelleyMA
|
||||
*pallas-applying/tests/byron.rs* contains multiple unit tests for validation on the ShelleyMA era, which is composed of the Shelley era itself as well as its two hardforks, Allegra and Mary.
|
||||
*pallas-applying/tests/shelley_ma_.rs* contains multiple unit tests for validation in the ShelleyMA era, which is composed of the Shelley era itself as well as its two hardforks, Allegra and Mary.
|
||||
|
||||
Note that, since phase-1 validations do not include the execution of native scripts or any of their extensions introduced in Allegra and Mary, there is virtually no difference between the Shelley era and the Allegra hardfork. The Mary hardfork does however introduce features involved in phase-1 validations, namely checking whether the policies of all minted / burnt assets have a matching native script in the transaction witnesses set.
|
||||
|
||||
|
|
@ -45,3 +45,45 @@ List of negative unit tests:
|
|||
- **missing_vk_witness** takes successful_mainnet_shelley_tx and removes the verification-key witness associated to one of its inputs.
|
||||
- **vk_witness_changed** takes successful_mainnet_shelley_tx and modifies the verification-key witness associated to one of its inputs.
|
||||
- **missing_native_script_witness** takes successful_mainnet_shelley_tx_with_script and removes the native script associated to one of its inputs.
|
||||
|
||||
### Alonzo
|
||||
*pallas-applying/tests/alonzo.rs* contains multiple unit tests for validation in the Alonzo era.
|
||||
|
||||
Note that phase-1 validations do not include the execution of native scripts or Plutus scripts, which would correspond to phase-2 validations.
|
||||
|
||||
List of positive unit tests:
|
||||
- **successful_mainnet_tx** ([here](https://cexplorer.io/tx/704b3b9c96f44cd5676e5dcb5dc0bb2555c66427625ccefe620101665da86868) to see on Cardano explorer) is a simple Alonzo transaction, with no native or Plutus scripts, no metadata, and no minting.
|
||||
- **successful_mainnet_tx_with_plutus_script** ([here](https://cexplorer.io/tx/65160f403d2c7419784ae997d32b93a6679d81468af8173ccd7949df6704f7ba) to see on Cardano explorer) is an Alonzo transaction with a Plutus script (including the related data structure, like redeemers, datums, collateral inputs), but no metadata or minting.
|
||||
- **successful_mainnet_tx_with_minting** ([here](https://cexplorer.io/tx/c220e20cc480df9ce7cd871df491d7390c6a004b9252cf20f45fc3c968535b4a) to see on Cardano Explorer) is an Alonzo transaction with metadata, but no native or Plutus scripts, and no minting.
|
||||
- **successful_mainnet_tx_with_metadata** ([here](https://cexplorer.io/tx/8b6debb3340e5dac098ddb25fa647a99de12a6c1987c98b17ae074d6917dba16) to see on Cardano Explorer) is an Alonzo transaction containing metadata, but no scripts (native or Plutus) and no minting.
|
||||
|
||||
List of negative unit tests:
|
||||
- **empty_ins** takes successful_mainnet_tx and removes its input.
|
||||
- **unfound_utxo_input** takes successful_mainnet_tx and calls validation on it with an empty UTxO (which causes the input to be unfound).
|
||||
- **validity_interval_lower_bound_unreached** takes sucessful_mainnet_tx and modifies its time interval in such a way that its validity time interval *lower* bound is located exactly one slot after the block slot.
|
||||
- **validity_interval_upper_bound_surpassed** takes sucessful_mainnt_tx and modifies its time interval in such a way that its validity time interval *upper* bound is located exactly one slot before the block slot.
|
||||
- **min_fees_unreached** submits validation on sucessful_mainnet_tx with an environment requesting the minimum fee to be higher than the one that the transaction actually paid.
|
||||
- **no_collateral_inputs** takes successful_mainnet_tx_with_plutus_script and removes its collateral inputs before submitting the transaction for validation.
|
||||
- **too_many_collateral_inputs** takes successful_mainnet_tx_with_plutus_script and submits its for validation with an environment allowing no collateral inputs.
|
||||
- **collateral_is_not_verification_key_locked** takes sucessful_mainnet_tx_with_plutus_script and modifies the address of one of the collateral inputs to become a script-locked output instead of a verification-key-locked one.
|
||||
- **collateral_with_other_assets** takes sucessful_mainnet_tx_with_plutus_script and adds non-lovelace assets to it.
|
||||
- **collateral_without_min_lovelace** takes sucessful_mainnet_tx_with_plutus_script and submits it for validation with an environment requesting a higher lovelace percentage (when compared to the fee paid by the transaction) in collateral inputs than the actual amount paid by the transaction collateral.
|
||||
- **preservation_of_value** modifies sucessful_mainnet_tx_with_plutus_script in such a way that the preservation-of-value equality does not hold.
|
||||
- **output_network_ids** takes sucessful_mainnet_tx and modifies the network ID in the address of one of its outputs.
|
||||
- **tx_network_id** takes sucessful_mainnet_tx and modifies its network ID.
|
||||
- **tx_ex_units_exceeded** takes sucessful_mainnet_tx_with_plutus_script and validates it with an environment whose Plutus script execution values are below the needs of the transaction.
|
||||
- **max_tx_size_exceeded** takes sucessful_mainnet_tx and validates it with an environment allowing only transactions whose size is lower than that of sucessful_mainnet_tx.
|
||||
- **missing_required_signer** takes sucessful_mainnet_tx_with_plutus_script and submits it for validation after changing one of the required signers.
|
||||
- **missing_vk_witness** removes a verification-key witness from sucessful_mainnet_tx befor submitting it for validation.
|
||||
- **wrong_signature** modifies the signature of the verification-key witness in sucessful_mainnet_tx before trying to validate it.
|
||||
- **missing_plutus_script** takes sucessful_mainnet_tx_with_plutus_script and removes its Plutus script before submitting it for validation.
|
||||
- **extra_plutus_script** takes sucessful_mainnet_tx_with_plutus_script and adds a new, unneeded native script to its witness set.
|
||||
- **minting_lacks_policy** takes sucessful_mainnet_tx_with_minting and removes the native script policy contained in it before submitting it for validation.
|
||||
- **missing_input_datum** takes sucessful_mainnet_tx_with_plutus_script and removes the datum contained in its witness set.
|
||||
- **extra_input_datum** takes sucessful_mainnet_tx_with_plutus_script and adds an unneded datum to its witness set.
|
||||
- **extra_redeemer** takes sucessful_mainnet_tx_with_plutus_script and adds an unneeded redeemer to its witness set.
|
||||
- **missing_redeemer** takes sucessful_mainnet_tx_with_plutus_script and removes its redeemer.
|
||||
- **auxiliary_data_removed** takes sucessful_mainnet_tx_with_metadata and removes its auxiliary data (a.k.a. metadata).
|
||||
- **min_lovelace_unreached** takes sucessful_mainnet_tx and submits validation on it with an environment requesting more lovelace on outputs than the amount actually paid by one of the outputs of the transaction.
|
||||
- **max_val_exceeded** takes sucessful_mainnet_tx and submits validation on it with an environment disallowing value sizes as high as the size ofg one of the values in one of the transaction outputs of sucessful_mainnet_tx.
|
||||
- **script_integrity_hash** takes sucessful_mainnet_tx_with_plutus_script and modifies the execution values of one of the redeemers in the witness set of the transaction, in such a way that all checks pass but the integrity hash of script-related data of the transaction is different from the script data hash contained in the body of the transaction.
|
||||
|
|
|
|||
2780
pallas-applying/tests/alonzo.rs
Normal file
2780
pallas-applying/tests/alonzo.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,67 +1,41 @@
|
|||
use std::{borrow::Cow, vec::Vec};
|
||||
pub mod common;
|
||||
|
||||
use common::{cbor_to_bytes, minted_tx_payload_from_cbor, mk_utxo_for_byron_tx};
|
||||
use pallas_applying::{
|
||||
types::{
|
||||
ByronError::*, ByronProtParams, Environment, FeePolicy, MultiEraProtParams,
|
||||
ValidationError::*,
|
||||
utils::{
|
||||
ByronError, ByronProtParams, Environment, FeePolicy, MultiEraProtParams, ValidationError::*,
|
||||
},
|
||||
validate, UTxOs,
|
||||
};
|
||||
|
||||
use pallas_codec::{
|
||||
minicbor::{
|
||||
bytes::ByteVec,
|
||||
decode::{Decode, Decoder},
|
||||
encode,
|
||||
},
|
||||
utils::{CborWrap, MaybeIndefArray, TagWrap},
|
||||
utils::{CborWrap, MaybeIndefArray},
|
||||
};
|
||||
use pallas_primitives::byron::{Address, MintedTxPayload, Twit, Tx, TxIn, TxOut, Witnesses};
|
||||
use pallas_traverse::{MultiEraInput, MultiEraOutput, MultiEraTx};
|
||||
use pallas_primitives::byron::{MintedTxPayload, Twit, Tx, TxOut, Witnesses};
|
||||
use pallas_traverse::MultiEraTx;
|
||||
use std::vec::Vec;
|
||||
|
||||
#[cfg(test)]
|
||||
mod byron_tests {
|
||||
use super::*;
|
||||
|
||||
fn cbor_to_bytes(input: &str) -> Vec<u8> {
|
||||
hex::decode(input).unwrap()
|
||||
}
|
||||
|
||||
fn tx_from_cbor<'a>(tx_cbor: &'a Vec<u8>) -> MintedTxPayload<'a> {
|
||||
pallas_codec::minicbor::decode::<MintedTxPayload>(&tx_cbor[..]).unwrap()
|
||||
}
|
||||
|
||||
// Careful: this function assumes tx has exactly one input.
|
||||
fn mk_utxo_for_single_input_tx<'a>(tx: &Tx, address_payload: String, amount: u64) -> UTxOs<'a> {
|
||||
let mut tx_ins: Vec<TxIn> = tx.inputs.clone().to_vec();
|
||||
assert_eq!(tx_ins.len(), 1, "Unexpected number of inputs");
|
||||
let tx_in: TxIn = tx_ins.pop().unwrap();
|
||||
let input_tx_out_addr: Address = match hex::decode(address_payload) {
|
||||
Ok(addr_bytes) => Address {
|
||||
payload: TagWrap(ByteVec::from(addr_bytes)),
|
||||
crc: 3430631884,
|
||||
},
|
||||
_ => panic!("Unable to decode input address"),
|
||||
};
|
||||
let tx_out: TxOut = TxOut {
|
||||
address: input_tx_out_addr,
|
||||
amount,
|
||||
};
|
||||
let mut utxos: UTxOs = UTxOs::new();
|
||||
add_to_utxo(&mut utxos, tx_in, tx_out);
|
||||
utxos
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Transaction hash:
|
||||
// a9e4413a5fb61a7a43c7df006ffcaaf3f2ffc9541f54757023968c5a8f8294fd
|
||||
fn successful_mainnet_tx_with_genesis_utxos() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron2.tx"));
|
||||
let mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron2.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron2.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -86,12 +60,14 @@ mod byron_tests {
|
|||
// a06e5a0150e09f8983be2deafab9e04afc60d92e7110999eb672c903343f1e26
|
||||
fn successful_mainnet_tx() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -115,11 +91,13 @@ mod byron_tests {
|
|||
// Identical to successful_mainnet_tx, except that all inputs are removed.
|
||||
fn empty_ins() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mut mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let mut mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
// Clear the set of inputs in the transaction.
|
||||
let mut tx: Tx = (*mtxp.transaction).clone();
|
||||
|
|
@ -146,7 +124,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Inputs set should not be empty"),
|
||||
Err(err) => match err {
|
||||
Byron(TxInsEmpty) => (),
|
||||
Byron(ByronError::TxInsEmpty) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -156,7 +134,7 @@ mod byron_tests {
|
|||
// Identical to successful_mainnet_tx, except that all outputs are removed.
|
||||
fn empty_outs() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mut mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mut mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
// Clear the set of outputs in the transaction.
|
||||
let mut tx: Tx = (*mtxp.transaction).clone();
|
||||
tx.outputs = MaybeIndefArray::Def(Vec::new());
|
||||
|
|
@ -167,10 +145,12 @@ mod byron_tests {
|
|||
};
|
||||
mtxp.transaction = Decode::decode(&mut Decoder::new(&tx_buf.as_slice()), &mut ()).unwrap();
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -187,7 +167,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Outputs set should not be empty"),
|
||||
Err(err) => match err {
|
||||
Byron(TxOutsEmpty) => (),
|
||||
Byron(ByronError::TxOutsEmpty) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -197,7 +177,7 @@ mod byron_tests {
|
|||
// The transaction is valid, but the UTxO set is empty.
|
||||
fn unfound_utxo() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = UTxOs::new();
|
||||
let env: Environment = Environment {
|
||||
|
|
@ -215,7 +195,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "All inputs must be within the UTxO set"),
|
||||
Err(err) => match err {
|
||||
Byron(InputNotInUTxO) => (),
|
||||
Byron(ByronError::InputNotInUTxO) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -225,7 +205,7 @@ mod byron_tests {
|
|||
// All lovelace in one of the outputs was removed.
|
||||
fn output_without_lovelace() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mut mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mut mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
// Remove lovelace from output.
|
||||
let mut tx: Tx = (*mtxp.transaction).clone();
|
||||
let altered_tx_out: TxOut = TxOut {
|
||||
|
|
@ -242,10 +222,12 @@ mod byron_tests {
|
|||
};
|
||||
mtxp.transaction = Decode::decode(&mut Decoder::new(&tx_buf.as_slice()), &mut ()).unwrap();
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -262,7 +244,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "All outputs must contain lovelace"),
|
||||
Err(err) => match err {
|
||||
Byron(OutputWithoutLovelace) => (),
|
||||
Byron(ByronError::OutputWithoutLovelace) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -272,12 +254,14 @@ mod byron_tests {
|
|||
// Expected fees are increased by increasing the protocol parameters.
|
||||
fn not_enough_fees() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -294,7 +278,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Fees should not be below minimum"),
|
||||
Err(err) => match err {
|
||||
Byron(FeesBelowMin) => (),
|
||||
Byron(ByronError::FeesBelowMin) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -304,12 +288,14 @@ mod byron_tests {
|
|||
// Tx size limit set by protocol parameters is established at 0.
|
||||
fn tx_size_exceeds_max() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -326,7 +312,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Transaction size cannot exceed protocol limit"),
|
||||
Err(err) => match err {
|
||||
Byron(MaxTxSizeExceeded) => (),
|
||||
Byron(ByronError::MaxTxSizeExceeded) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -336,7 +322,7 @@ mod byron_tests {
|
|||
// The input to the transaction does not have a corresponding witness.
|
||||
fn missing_witness() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mut mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mut mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
// Remove witness
|
||||
let new_witnesses: Witnesses = MaybeIndefArray::Def(Vec::new());
|
||||
let mut tx_buf: Vec<u8> = Vec::new();
|
||||
|
|
@ -346,10 +332,12 @@ mod byron_tests {
|
|||
};
|
||||
mtxp.witness = Decode::decode(&mut Decoder::new(&tx_buf.as_slice()), &mut ()).unwrap();
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -366,7 +354,7 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "All inputs must have a witness signature"),
|
||||
Err(err) => match err {
|
||||
Byron(MissingWitness) => (),
|
||||
Byron(ByronError::MissingWitness) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -377,7 +365,7 @@ mod byron_tests {
|
|||
// wrong.
|
||||
fn wrong_signature() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/byron1.tx"));
|
||||
let mut mtxp: MintedTxPayload = tx_from_cbor(&cbor_bytes);
|
||||
let mut mtxp: MintedTxPayload = minted_tx_payload_from_cbor(&cbor_bytes);
|
||||
// Modify signature in witness
|
||||
let new_wit: Twit = match mtxp.witness[0].clone() {
|
||||
Twit::PkWitness(CborWrap((pk, _))) => {
|
||||
|
|
@ -395,10 +383,12 @@ mod byron_tests {
|
|||
};
|
||||
mtxp.witness = Decode::decode(&mut Decoder::new(&tx_buf.as_slice()), &mut ()).unwrap();
|
||||
let metx: MultiEraTx = MultiEraTx::from_byron(&mtxp);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_byron_tx(
|
||||
&mtxp.transaction,
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/byron1.address")),
|
||||
19999000000,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Byron(ByronProtParams {
|
||||
|
|
@ -415,16 +405,9 @@ mod byron_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Witness signature should verify the transaction"),
|
||||
Err(err) => match err {
|
||||
Byron(WrongSignature) => (),
|
||||
Byron(ByronError::WrongSignature) => (),
|
||||
_ => panic!("Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions.
|
||||
fn add_to_utxo<'a>(utxos: &mut UTxOs<'a>, tx_in: TxIn, tx_out: TxOut) {
|
||||
let multi_era_in: MultiEraInput = MultiEraInput::Byron(Box::new(Cow::Owned(tx_in)));
|
||||
let multi_era_out: MultiEraOutput = MultiEraOutput::Byron(Box::new(Cow::Owned(tx_out)));
|
||||
utxos.insert(multi_era_in, multi_era_out);
|
||||
}
|
||||
|
|
|
|||
96
pallas-applying/tests/common.rs
Normal file
96
pallas-applying/tests/common.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
use pallas_applying::UTxOs;
|
||||
use pallas_codec::{minicbor::bytes::ByteVec, utils::TagWrap};
|
||||
use pallas_primitives::{
|
||||
alonzo::{MintedTx, TransactionBody, TransactionOutput, Value},
|
||||
byron::{Address, MintedTxPayload, Tx, TxOut},
|
||||
};
|
||||
use pallas_traverse::{MultiEraInput, MultiEraOutput};
|
||||
use std::{borrow::Cow, iter::zip, vec::Vec};
|
||||
|
||||
use pallas_codec::utils::Bytes;
|
||||
use pallas_crypto::hash::Hash;
|
||||
|
||||
pub fn cbor_to_bytes(input: &str) -> Vec<u8> {
|
||||
hex::decode(input).unwrap()
|
||||
}
|
||||
|
||||
pub fn minted_tx_from_cbor<'a>(tx_cbor: &'a Vec<u8>) -> MintedTx<'a> {
|
||||
pallas_codec::minicbor::decode::<MintedTx>(&tx_cbor[..]).unwrap()
|
||||
}
|
||||
|
||||
pub fn minted_tx_payload_from_cbor<'a>(tx_cbor: &'a Vec<u8>) -> MintedTxPayload<'a> {
|
||||
pallas_codec::minicbor::decode::<MintedTxPayload>(&tx_cbor[..]).unwrap()
|
||||
}
|
||||
|
||||
pub fn mk_utxo_for_byron_tx<'a>(tx: &Tx, tx_outs_info: &[(String, u64)]) -> UTxOs<'a> {
|
||||
let mut utxos: UTxOs = UTxOs::new();
|
||||
for (tx_in, (address_payload, amount)) in zip(tx.inputs.clone().to_vec(), tx_outs_info) {
|
||||
let input_tx_out_addr: Address = match hex::decode(address_payload) {
|
||||
Ok(addr_bytes) => Address {
|
||||
payload: TagWrap(ByteVec::from(addr_bytes)),
|
||||
crc: 3430631884,
|
||||
},
|
||||
_ => panic!("Unable to decode input address"),
|
||||
};
|
||||
let tx_out: TxOut = TxOut {
|
||||
address: input_tx_out_addr,
|
||||
amount: amount.clone(),
|
||||
};
|
||||
let multi_era_in: MultiEraInput = MultiEraInput::Byron(Box::new(Cow::Owned(tx_in)));
|
||||
let multi_era_out: MultiEraOutput = MultiEraOutput::Byron(Box::new(Cow::Owned(tx_out)));
|
||||
utxos.insert(multi_era_in, multi_era_out);
|
||||
}
|
||||
utxos
|
||||
}
|
||||
|
||||
pub fn mk_utxo_for_alonzo_compatible_tx<'a>(
|
||||
tx_body: &TransactionBody,
|
||||
tx_outs_info: &[(String, Value, Option<Hash<32>>)],
|
||||
) -> UTxOs<'a> {
|
||||
let mut utxos: UTxOs = UTxOs::new();
|
||||
for (tx_in, (address, amount, datum_hash)) in zip(tx_body.inputs.clone(), tx_outs_info) {
|
||||
let address_bytes: Bytes = match hex::decode(address) {
|
||||
Ok(bytes_vec) => Bytes::from(bytes_vec),
|
||||
_ => panic!("Unable to decode input address"),
|
||||
};
|
||||
let tx_out: TransactionOutput = TransactionOutput {
|
||||
address: address_bytes,
|
||||
amount: amount.clone(),
|
||||
datum_hash: datum_hash.clone(),
|
||||
};
|
||||
let multi_era_in: MultiEraInput =
|
||||
MultiEraInput::AlonzoCompatible(Box::new(Cow::Owned(tx_in)));
|
||||
let multi_era_out: MultiEraOutput =
|
||||
MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out)));
|
||||
utxos.insert(multi_era_in, multi_era_out);
|
||||
}
|
||||
utxos
|
||||
}
|
||||
|
||||
pub fn add_collateral<'a>(
|
||||
tx_body: &TransactionBody,
|
||||
utxos: &mut UTxOs<'a>,
|
||||
collateral_info: &[(String, Value, Option<Hash<32>>)],
|
||||
) {
|
||||
match &tx_body.collateral {
|
||||
Some(collaterals) => {
|
||||
for (tx_in, (address, amount, datum_hash)) in zip(collaterals, collateral_info) {
|
||||
let address_bytes: Bytes = match hex::decode(address) {
|
||||
Ok(bytes_vec) => Bytes::from(bytes_vec),
|
||||
_ => panic!("Unable to decode input address"),
|
||||
};
|
||||
let tx_out: TransactionOutput = TransactionOutput {
|
||||
address: address_bytes,
|
||||
amount: amount.clone(),
|
||||
datum_hash: datum_hash.clone(),
|
||||
};
|
||||
let multi_era_in: MultiEraInput =
|
||||
MultiEraInput::AlonzoCompatible(Box::new(Cow::Owned(tx_in.clone())));
|
||||
let multi_era_out: MultiEraOutput =
|
||||
MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out)));
|
||||
utxos.insert(multi_era_in, multi_era_out);
|
||||
}
|
||||
}
|
||||
None => panic!("Adding collateral to UTxO failed due to an empty list of collaterals"),
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
use std::borrow::Cow;
|
||||
pub mod common;
|
||||
|
||||
use common::*;
|
||||
use pallas_addresses::{Address, Network, ShelleyAddress};
|
||||
use pallas_applying::{
|
||||
types::{
|
||||
Environment, FeePolicy, MultiEraProtParams, ShelleyMAError::*, ShelleyProtParams,
|
||||
utils::{
|
||||
Environment, FeePolicy, MultiEraProtParams, ShelleyMAError, ShelleyProtParams,
|
||||
ValidationError::*,
|
||||
},
|
||||
validate, UTxOs,
|
||||
|
|
@ -13,51 +14,17 @@ use pallas_codec::{
|
|||
decode::{Decode, Decoder},
|
||||
encode,
|
||||
},
|
||||
utils::Bytes,
|
||||
utils::{Bytes, Nullable},
|
||||
};
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::alonzo::{
|
||||
MintedTx, MintedWitnessSet, TransactionBody, TransactionInput, TransactionOutput, VKeyWitness,
|
||||
Value,
|
||||
MintedTx, MintedWitnessSet, TransactionBody, TransactionOutput, VKeyWitness, Value,
|
||||
};
|
||||
use pallas_traverse::{Era, MultiEraInput, MultiEraOutput, MultiEraTx};
|
||||
use pallas_traverse::{Era, MultiEraTx};
|
||||
|
||||
#[cfg(test)]
|
||||
mod shelley_tests {
|
||||
mod shelley_ma_tests {
|
||||
use super::*;
|
||||
|
||||
fn cbor_to_bytes(input: &str) -> Vec<u8> {
|
||||
hex::decode(input).unwrap()
|
||||
}
|
||||
|
||||
fn minted_tx_from_cbor<'a>(tx_cbor: &'a Vec<u8>) -> MintedTx<'a> {
|
||||
pallas_codec::minicbor::decode::<MintedTx>(&tx_cbor[..]).unwrap()
|
||||
}
|
||||
|
||||
// Careful: this function assumes tx_body has exactly one input.
|
||||
fn mk_utxo_for_single_input_tx<'a>(
|
||||
tx_body: &TransactionBody,
|
||||
address: String,
|
||||
amount: Value,
|
||||
datum_hash: Option<Hash<32>>,
|
||||
) -> UTxOs<'a> {
|
||||
let tx_ins: &Vec<TransactionInput> = &tx_body.inputs;
|
||||
assert_eq!(tx_ins.len(), 1, "Unexpected number of inputs");
|
||||
let tx_in: TransactionInput = tx_ins.first().unwrap().clone();
|
||||
let address_bytes: Bytes = match hex::decode(address) {
|
||||
Ok(bytes_vec) => Bytes::from(bytes_vec),
|
||||
_ => panic!("Unable to decode input address"),
|
||||
};
|
||||
let tx_out: TransactionOutput = TransactionOutput {
|
||||
address: address_bytes,
|
||||
amount,
|
||||
datum_hash,
|
||||
};
|
||||
let mut utxos: UTxOs = UTxOs::new();
|
||||
add_to_utxo(&mut utxos, tx_in, tx_out);
|
||||
utxos
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Transaction hash:
|
||||
// 50eba65e73c8c5f7b09f4ea28cf15dce169f3d1c322ca3deff03725f51518bb2
|
||||
|
|
@ -65,11 +32,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -97,11 +66,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley2.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley2.address")),
|
||||
Value::Coin(2000000),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley2.address")),
|
||||
Value::Coin(2000000),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -129,11 +100,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley3.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley3.address")),
|
||||
Value::Coin(10000000),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley3.address")),
|
||||
Value::Coin(10000000),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -161,11 +134,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/mary1.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Mary);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/mary1.address")),
|
||||
Value::Coin(3500000),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/mary1.address")),
|
||||
Value::Coin(3500000),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -191,14 +166,16 @@ mod shelley_tests {
|
|||
fn empty_ins() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
// Clear the set of inputs in the transaction.
|
||||
let mut tx_body: TransactionBody = (*mtx.transaction_body).clone();
|
||||
let mut tx_body: TransactionBody = mtx.transaction_body.unwrap().clone();
|
||||
tx_body.inputs = Vec::new();
|
||||
let mut tx_buf: Vec<u8> = Vec::new();
|
||||
match encode(tx_body, &mut tx_buf) {
|
||||
|
|
@ -224,7 +201,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Inputs set should not be empty"),
|
||||
Err(err) => match err {
|
||||
Shelley(TxInsEmpty) => (),
|
||||
ShelleyMA(ShelleyMAError::TxInsEmpty) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -253,7 +230,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "All inputs must be within the UTxO set"),
|
||||
Err(err) => match err {
|
||||
Shelley(InputNotInUTxO) => (),
|
||||
ShelleyMA(ShelleyMAError::InputNotInUTxO) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -264,13 +241,15 @@ mod shelley_tests {
|
|||
fn missing_ttl() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let mut tx_body: TransactionBody = (*mtx.transaction_body).clone();
|
||||
let mut tx_body: TransactionBody = mtx.transaction_body.unwrap().clone();
|
||||
tx_body.ttl = None;
|
||||
let mut tx_buf: Vec<u8> = Vec::new();
|
||||
match encode(tx_body, &mut tx_buf) {
|
||||
|
|
@ -296,7 +275,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "TTL must always be present in Shelley transactions"),
|
||||
Err(err) => match err {
|
||||
Shelley(AlonzoCompNotShelley) => (),
|
||||
ShelleyMA(ShelleyMAError::AlonzoCompNotShelley) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -308,11 +287,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -330,7 +311,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "TTL cannot be exceeded"),
|
||||
Err(err) => match err {
|
||||
Shelley(TTLExceeded) => (),
|
||||
ShelleyMA(ShelleyMAError::TTLExceeded) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -342,11 +323,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -364,7 +347,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Tx size exceeds max limit"),
|
||||
Err(err) => match err {
|
||||
Shelley(MaxTxSizeExceeded) => (),
|
||||
ShelleyMA(ShelleyMAError::MaxTxSizeExceeded) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -377,11 +360,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -399,7 +384,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Output amount must be above min lovelace value"),
|
||||
Err(err) => match err {
|
||||
Shelley(MinLovelaceUnreached) => (),
|
||||
ShelleyMA(ShelleyMAError::MinLovelaceUnreached) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -411,7 +396,7 @@ mod shelley_tests {
|
|||
fn preservation_of_value() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let mut tx_body: TransactionBody = (*mtx.transaction_body).clone();
|
||||
let mut tx_body: TransactionBody = mtx.transaction_body.unwrap().clone();
|
||||
tx_body.fee = tx_body.fee - 1;
|
||||
let mut tx_buf: Vec<u8> = Vec::new();
|
||||
match encode(tx_body, &mut tx_buf) {
|
||||
|
|
@ -421,11 +406,13 @@ mod shelley_tests {
|
|||
mtx.transaction_body =
|
||||
Decode::decode(&mut Decoder::new(&tx_buf.as_slice()), &mut ()).unwrap();
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -443,7 +430,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Preservation of value property doesn't hold"),
|
||||
Err(err) => match err {
|
||||
Shelley(PreservationOfValue) => (),
|
||||
ShelleyMA(ShelleyMAError::PreservationOfValue) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -455,11 +442,13 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -477,7 +466,7 @@ mod shelley_tests {
|
|||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Fee should not be below minimum"),
|
||||
Err(err) => match err {
|
||||
Shelley(FeesBelowMin) => (),
|
||||
ShelleyMA(ShelleyMAError::FeesBelowMin) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -490,7 +479,7 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
// Modify the first output address.
|
||||
let mut tx_body: TransactionBody = (*mtx.transaction_body).clone();
|
||||
let mut tx_body: TransactionBody = mtx.transaction_body.unwrap().clone();
|
||||
let (first_output, rest): (&TransactionOutput, &[TransactionOutput]) =
|
||||
(&tx_body.outputs).split_first().unwrap();
|
||||
let addr: ShelleyAddress =
|
||||
|
|
@ -533,33 +522,39 @@ mod shelley_tests {
|
|||
block_slot: 5281340,
|
||||
network_id: 1,
|
||||
};
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Output with wrong network ID should be rejected"),
|
||||
Err(err) => match err {
|
||||
Shelley(WrongNetworkID) => (),
|
||||
ShelleyMA(ShelleyMAError::WrongNetworkID) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Like successful_mainnet_shelley_tx_with_metadata (hash:
|
||||
// c220e20cc480df9ce7cd871df491d7390c6a004b9252cf20f45fc3c968535b4a)
|
||||
// Same as successful_mainnet_shelley_tx_with_metadata (hash:
|
||||
// c220e20cc480df9ce7cd871df491d7390c6a004b9252cf20f45fc3c968535b4a), except
|
||||
// that the AuxiliaryData is removed.
|
||||
fn auxiliary_data_removed() {
|
||||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley3.tx"));
|
||||
let mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
mtx.auxiliary_data = Nullable::Null;
|
||||
let metx: MultiEraTx = MultiEraTx::from_alonzo_compatible(&mtx, Era::Shelley);
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley3.address")),
|
||||
Value::Coin(10000000),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley3.address")),
|
||||
Value::Coin(10000000),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
let env: Environment = Environment {
|
||||
prot_params: MultiEraProtParams::Shelley(ShelleyProtParams {
|
||||
|
|
@ -575,8 +570,11 @@ mod shelley_tests {
|
|||
network_id: 1,
|
||||
};
|
||||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => (),
|
||||
Err(err) => assert!(false, "Unexpected error ({:?})", err),
|
||||
Ok(()) => assert!(false, "Output with wrong network ID should be rejected"),
|
||||
Err(err) => match err {
|
||||
ShelleyMA(ShelleyMAError::MetadataHash) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -588,7 +586,7 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
// Modify the first output address.
|
||||
let mut tx_wits: MintedWitnessSet = (*mtx.transaction_witness_set).clone();
|
||||
let mut tx_wits: MintedWitnessSet = mtx.transaction_witness_set.unwrap().clone();
|
||||
tx_wits.vkeywitness = Some(Vec::new());
|
||||
let mut tx_buf: Vec<u8> = Vec::new();
|
||||
match encode(tx_wits, &mut tx_buf) {
|
||||
|
|
@ -611,16 +609,18 @@ mod shelley_tests {
|
|||
block_slot: 5281340,
|
||||
network_id: 1,
|
||||
};
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Missing verification key witness"),
|
||||
Err(err) => match err {
|
||||
Shelley(MissingVKWitness) => (),
|
||||
ShelleyMA(ShelleyMAError::MissingVKWitness) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -634,7 +634,7 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley1.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
// Modify the first output address.
|
||||
let mut tx_wits: MintedWitnessSet = (*mtx.transaction_witness_set).clone();
|
||||
let mut tx_wits: MintedWitnessSet = mtx.transaction_witness_set.unwrap().clone();
|
||||
let mut wit: VKeyWitness = tx_wits.vkeywitness.clone().unwrap().pop().unwrap();
|
||||
let mut sig_as_vec: Vec<u8> = wit.signature.to_vec();
|
||||
sig_as_vec.pop();
|
||||
|
|
@ -662,16 +662,18 @@ mod shelley_tests {
|
|||
block_slot: 5281340,
|
||||
network_id: 1,
|
||||
};
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley1.address")),
|
||||
Value::Coin(2332267427205),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Missing verification key witness"),
|
||||
Err(err) => match err {
|
||||
Shelley(WrongSignature) => (),
|
||||
ShelleyMA(ShelleyMAError::WrongSignature) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
|
|
@ -685,7 +687,7 @@ mod shelley_tests {
|
|||
let cbor_bytes: Vec<u8> = cbor_to_bytes(include_str!("../../test_data/shelley2.tx"));
|
||||
let mut mtx: MintedTx = minted_tx_from_cbor(&cbor_bytes);
|
||||
// Modify the first output address.
|
||||
let mut tx_wits: MintedWitnessSet = (*mtx.transaction_witness_set).clone();
|
||||
let mut tx_wits: MintedWitnessSet = mtx.transaction_witness_set.unwrap().clone();
|
||||
tx_wits.native_script = Some(Vec::new());
|
||||
let mut tx_buf: Vec<u8> = Vec::new();
|
||||
match encode(tx_wits, &mut tx_buf) {
|
||||
|
|
@ -708,26 +710,20 @@ mod shelley_tests {
|
|||
block_slot: 5281340,
|
||||
network_id: 1,
|
||||
};
|
||||
let utxos: UTxOs = mk_utxo_for_single_input_tx(
|
||||
let utxos: UTxOs = mk_utxo_for_alonzo_compatible_tx(
|
||||
&mtx.transaction_body,
|
||||
String::from(include_str!("../../test_data/shelley2.address")),
|
||||
Value::Coin(2000000),
|
||||
None,
|
||||
&[(
|
||||
String::from(include_str!("../../test_data/shelley2.address")),
|
||||
Value::Coin(2000000),
|
||||
None,
|
||||
)],
|
||||
);
|
||||
match validate(&metx, &utxos, &env) {
|
||||
Ok(()) => assert!(false, "Missing native script witness"),
|
||||
Err(err) => match err {
|
||||
Shelley(MissingScriptWitness) => (),
|
||||
ShelleyMA(ShelleyMAError::MissingScriptWitness) => (),
|
||||
_ => assert!(false, "Unexpected error ({:?})", err),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions.
|
||||
fn add_to_utxo<'a>(utxos: &mut UTxOs<'a>, tx_in: TransactionInput, tx_out: TransactionOutput) {
|
||||
let multi_era_in: MultiEraInput = MultiEraInput::AlonzoCompatible(Box::new(Cow::Owned(tx_in)));
|
||||
let multi_era_out: MultiEraOutput =
|
||||
MultiEraOutput::AlonzoCompatible(Box::new(Cow::Owned(tx_out)));
|
||||
utxos.insert(multi_era_in, multi_era_out);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue