Replaced unreachable statements with Error
This commit is contained in:
		
							parent
							
								
									1148863a43
								
							
						
					
					
						commit
						4a6496db3f
					
				| 
						 | 
					@ -21,6 +21,8 @@ pub enum Error {
 | 
				
			||||||
        missing: Vec<String>,
 | 
					        missing: Vec<String>,
 | 
				
			||||||
        extra: Vec<String>,
 | 
					        extra: Vec<String>,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    #[error("Extranous redeemer found: Tag {:?}, Index {}", tag, index)]
 | 
				
			||||||
 | 
					    ExtranousRedeemer { tag: String, index: u32 },
 | 
				
			||||||
    #[error("Resolved Input not found")]
 | 
					    #[error("Resolved Input not found")]
 | 
				
			||||||
    ResolvedInputNotFound,
 | 
					    ResolvedInputNotFound,
 | 
				
			||||||
    #[error("A key hash cannot be the hash of a script")]
 | 
					    #[error("A key hash cannot be the hash of a script")]
 | 
				
			||||||
| 
						 | 
					@ -31,4 +33,20 @@ pub enum Error {
 | 
				
			||||||
    V2CostModelNotFound,
 | 
					    V2CostModelNotFound,
 | 
				
			||||||
    #[error("Wrong era, Please use Babbage or Alonzo: {0}")]
 | 
					    #[error("Wrong era, Please use Babbage or Alonzo: {0}")]
 | 
				
			||||||
    WrongEra(#[from] pallas_codec::minicbor::decode::Error),
 | 
					    WrongEra(#[from] pallas_codec::minicbor::decode::Error),
 | 
				
			||||||
 | 
					    #[error("Byron address not allowed in Plutus.")]
 | 
				
			||||||
 | 
					    ByronAddressNotAllowed,
 | 
				
			||||||
 | 
					    #[error("Inline datum not allowed in PlutusV1.")]
 | 
				
			||||||
 | 
					    InlineDatumNotAllowed,
 | 
				
			||||||
 | 
					    #[error("Script and input reference not allowed in PlutusV1.")]
 | 
				
			||||||
 | 
					    ScriptAndInputRefNotAllowed,
 | 
				
			||||||
 | 
					    #[error("Address doesn't contain a payment credential.")]
 | 
				
			||||||
 | 
					    NoPaymentCredential,
 | 
				
			||||||
 | 
					    #[error("Missing required datum in witness set. Datum hash: {}", hash)]
 | 
				
			||||||
 | 
					    MissingRequiredDatum { hash: String },
 | 
				
			||||||
 | 
					    #[error("Missing required script. Script hash: {}", hash)]
 | 
				
			||||||
 | 
					    MissingRequiredScript { hash: String },
 | 
				
			||||||
 | 
					    #[error("Missing required inline datum or datum hash in script input.")]
 | 
				
			||||||
 | 
					    MissingRequiredInlineDatumOrHash,
 | 
				
			||||||
 | 
					    #[error("Only stake deregistration and delegation are valid certificate script purposes.")]
 | 
				
			||||||
 | 
					    OnlyStakeDeregAndDelegAllowed,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -67,12 +67,12 @@ pub fn get_tx_in_info_v1(
 | 
				
			||||||
    inputs: &[TransactionInput],
 | 
					    inputs: &[TransactionInput],
 | 
				
			||||||
    utxos: &[ResolvedInput],
 | 
					    utxos: &[ResolvedInput],
 | 
				
			||||||
) -> Result<Vec<TxInInfo>, Error> {
 | 
					) -> Result<Vec<TxInInfo>, Error> {
 | 
				
			||||||
    let result = inputs
 | 
					    inputs
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .map(|input| {
 | 
					        .map(|input| {
 | 
				
			||||||
            let utxo = match utxos.iter().find(|utxo| utxo.input == *input) {
 | 
					            let utxo = match utxos.iter().find(|utxo| utxo.input == *input) {
 | 
				
			||||||
                Some(u) => u,
 | 
					                Some(u) => u,
 | 
				
			||||||
                None => unreachable!("Resolved input not found."),
 | 
					                None => return Err(Error::ResolvedInputNotFound),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            let address = Address::from_bytes(match &utxo.output {
 | 
					            let address = Address::from_bytes(match &utxo.output {
 | 
				
			||||||
                TransactionOutput::Legacy(output) => output.address.as_ref(),
 | 
					                TransactionOutput::Legacy(output) => output.address.as_ref(),
 | 
				
			||||||
| 
						 | 
					@ -81,45 +81,46 @@ pub fn get_tx_in_info_v1(
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match address {
 | 
					            match address {
 | 
				
			||||||
                Address::Byron(_) => unreachable!("Byron addresses not supported in Plutus."),
 | 
					                Address::Byron(_) => {
 | 
				
			||||||
 | 
					                    return Err(Error::ByronAddressNotAllowed);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                Address::Stake(_) => {
 | 
					                Address::Stake(_) => {
 | 
				
			||||||
                    unreachable!("This is impossible. A stake address cannot lock a UTxO.")
 | 
					                    return Err(Error::NoPaymentCredential);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => {}
 | 
					                _ => {}
 | 
				
			||||||
            }
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match &utxo.output {
 | 
					            match &utxo.output {
 | 
				
			||||||
                TransactionOutput::Legacy(_) => {}
 | 
					                TransactionOutput::Legacy(_) => {}
 | 
				
			||||||
                TransactionOutput::PostAlonzo(output) => {
 | 
					                TransactionOutput::PostAlonzo(output) => {
 | 
				
			||||||
                    if let Some(DatumOption::Data(_)) = output.datum_option {
 | 
					                    if let Some(DatumOption::Data(_)) = output.datum_option {
 | 
				
			||||||
                        unreachable!("Inline datum not allowed in PlutusV1.")
 | 
					                        return Err(Error::InlineDatumNotAllowed);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if output.script_ref.is_some() {
 | 
					                    if output.script_ref.is_some() {
 | 
				
			||||||
                        unreachable!("Reference scripts not allowed in PlutusV1.")
 | 
					                        return Err(Error::ScriptAndInputRefNotAllowed);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            TxInInfo {
 | 
					            Ok(TxInInfo {
 | 
				
			||||||
                out_ref: utxo.input.clone(),
 | 
					                out_ref: utxo.input.clone(),
 | 
				
			||||||
                resolved: TxOut::V1(utxo.output.clone()),
 | 
					                resolved: TxOut::V1(utxo.output.clone()),
 | 
				
			||||||
            }
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .collect::<Vec<TxInInfo>>();
 | 
					        .collect()
 | 
				
			||||||
    Ok(result)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn get_tx_in_info_v2(
 | 
					fn get_tx_in_info_v2(
 | 
				
			||||||
    inputs: &[TransactionInput],
 | 
					    inputs: &[TransactionInput],
 | 
				
			||||||
    utxos: &[ResolvedInput],
 | 
					    utxos: &[ResolvedInput],
 | 
				
			||||||
) -> Result<Vec<TxInInfo>, Error> {
 | 
					) -> Result<Vec<TxInInfo>, Error> {
 | 
				
			||||||
    let result = inputs
 | 
					    inputs
 | 
				
			||||||
        .iter()
 | 
					        .iter()
 | 
				
			||||||
        .map(|input| {
 | 
					        .map(|input| {
 | 
				
			||||||
            let utxo = match utxos.iter().find(|utxo| utxo.input == *input) {
 | 
					            let utxo = match utxos.iter().find(|utxo| utxo.input == *input) {
 | 
				
			||||||
                Some(u) => u,
 | 
					                Some(u) => u,
 | 
				
			||||||
                None => unreachable!("Resolved input not found."),
 | 
					                None => return Err(Error::ResolvedInputNotFound),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            let address = Address::from_bytes(match &utxo.output {
 | 
					            let address = Address::from_bytes(match &utxo.output {
 | 
				
			||||||
                TransactionOutput::Legacy(output) => output.address.as_ref(),
 | 
					                TransactionOutput::Legacy(output) => output.address.as_ref(),
 | 
				
			||||||
| 
						 | 
					@ -128,20 +129,21 @@ fn get_tx_in_info_v2(
 | 
				
			||||||
            .unwrap();
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            match address {
 | 
					            match address {
 | 
				
			||||||
                Address::Byron(_) => unreachable!("Byron addresses not supported in Plutus."),
 | 
					                Address::Byron(_) => {
 | 
				
			||||||
 | 
					                    return Err(Error::ByronAddressNotAllowed);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                Address::Stake(_) => {
 | 
					                Address::Stake(_) => {
 | 
				
			||||||
                    unreachable!("This is impossible. A stake address cannot lock a UTxO.")
 | 
					                    return Err(Error::NoPaymentCredential);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                _ => {}
 | 
					                _ => {}
 | 
				
			||||||
            }
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            TxInInfo {
 | 
					            Ok(TxInInfo {
 | 
				
			||||||
                out_ref: utxo.input.clone(),
 | 
					                out_ref: utxo.input.clone(),
 | 
				
			||||||
                resolved: TxOut::V2(utxo.output.clone()),
 | 
					                resolved: TxOut::V2(utxo.output.clone()),
 | 
				
			||||||
            }
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .collect::<Vec<TxInInfo>>();
 | 
					        .collect()
 | 
				
			||||||
    Ok(result)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn get_script_purpose(
 | 
					fn get_script_purpose(
 | 
				
			||||||
| 
						 | 
					@ -166,23 +168,26 @@ fn get_script_purpose(
 | 
				
			||||||
            policy_ids.sort();
 | 
					            policy_ids.sort();
 | 
				
			||||||
            match policy_ids.get(index as usize) {
 | 
					            match policy_ids.get(index as usize) {
 | 
				
			||||||
                Some(policy_id) => Ok(ScriptPurpose::Minting(*policy_id)),
 | 
					                Some(policy_id) => Ok(ScriptPurpose::Minting(*policy_id)),
 | 
				
			||||||
                None => unreachable!("Script purpose not found for redeemer."),
 | 
					                None => {
 | 
				
			||||||
 | 
					                    return Err(Error::ExtranousRedeemer {
 | 
				
			||||||
 | 
					                        tag: "Mint".to_string(),
 | 
				
			||||||
 | 
					                        index,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        RedeemerTag::Spend => {
 | 
					        RedeemerTag::Spend => {
 | 
				
			||||||
            // sort lexical by tx_hash and index
 | 
					            // sort lexical by tx_hash and index
 | 
				
			||||||
            let mut inputs = inputs.to_vec();
 | 
					            let mut inputs = inputs.to_vec();
 | 
				
			||||||
            // is this correct? Does this sort lexical from low to high? maybe get Ordering into pallas for TransactionInput?
 | 
					            inputs.sort();
 | 
				
			||||||
            inputs.sort_by(
 | 
					 | 
				
			||||||
                |i_a, i_b| match i_a.transaction_id.cmp(&i_b.transaction_id) {
 | 
					 | 
				
			||||||
                    std::cmp::Ordering::Less => std::cmp::Ordering::Less,
 | 
					 | 
				
			||||||
                    std::cmp::Ordering::Equal => i_a.index.cmp(&i_b.index),
 | 
					 | 
				
			||||||
                    std::cmp::Ordering::Greater => std::cmp::Ordering::Greater,
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            match inputs.get(index as usize) {
 | 
					            match inputs.get(index as usize) {
 | 
				
			||||||
                Some(input) => Ok(ScriptPurpose::Spending(input.clone())),
 | 
					                Some(input) => Ok(ScriptPurpose::Spending(input.clone())),
 | 
				
			||||||
                None => unreachable!("Script purpose not found for redeemer."),
 | 
					                None => {
 | 
				
			||||||
 | 
					                    return Err(Error::ExtranousRedeemer {
 | 
				
			||||||
 | 
					                        tag: "Spend".to_string(),
 | 
				
			||||||
 | 
					                        index,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        RedeemerTag::Reward => {
 | 
					        RedeemerTag::Reward => {
 | 
				
			||||||
| 
						 | 
					@ -196,23 +201,22 @@ fn get_script_purpose(
 | 
				
			||||||
            reward_accounts.sort();
 | 
					            reward_accounts.sort();
 | 
				
			||||||
            let reward_account = match reward_accounts.get(index as usize) {
 | 
					            let reward_account = match reward_accounts.get(index as usize) {
 | 
				
			||||||
                Some(ra) => ra.clone(),
 | 
					                Some(ra) => ra.clone(),
 | 
				
			||||||
                None => unreachable!("Script purpose not found for redeemer."),
 | 
					                None => {
 | 
				
			||||||
 | 
					                    return Err(Error::ExtranousRedeemer {
 | 
				
			||||||
 | 
					                        tag: "Reward".to_string(),
 | 
				
			||||||
 | 
					                        index,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            let address = Address::from_bytes(&reward_account)?;
 | 
					            let address = Address::from_bytes(&reward_account)?;
 | 
				
			||||||
            let credential = match address {
 | 
					            let credential = match address {
 | 
				
			||||||
                Address::Stake(stake_address) => match stake_address.payload() {
 | 
					                Address::Stake(stake_address) => match stake_address.payload() {
 | 
				
			||||||
                    StakePayload::Script(script_hash) => {
 | 
					                    StakePayload::Script(script_hash) => StakeCredential::Scripthash(*script_hash),
 | 
				
			||||||
                        StakeCredential::Scripthash(*script_hash)
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    StakePayload::Stake(_) => {
 | 
					                    StakePayload::Stake(_) => {
 | 
				
			||||||
                        unreachable!(
 | 
					                        return Err(Error::ScriptKeyHash);
 | 
				
			||||||
                            "This is impossible. A key hash cannot be the hash of a script."
 | 
					 | 
				
			||||||
                        );
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                _ => unreachable!(
 | 
					                _ => return Err(Error::BadWithdrawalAddress),
 | 
				
			||||||
                    "This is impossible. Only shelley reward addresses can be a part of withdrawals."
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            Ok(ScriptPurpose::Rewarding(credential))
 | 
					            Ok(ScriptPurpose::Rewarding(credential))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -224,7 +228,12 @@ fn get_script_purpose(
 | 
				
			||||||
                .get(index as usize)
 | 
					                .get(index as usize)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Some(cert) => Ok(ScriptPurpose::Certifying(cert.clone())),
 | 
					                Some(cert) => Ok(ScriptPurpose::Certifying(cert.clone())),
 | 
				
			||||||
                None => unreachable!("Script purpose not found for redeemer."),
 | 
					                None => {
 | 
				
			||||||
 | 
					                    return Err(Error::ExtranousRedeemer {
 | 
				
			||||||
 | 
					                        tag: "Cert".to_string(),
 | 
				
			||||||
 | 
					                        index,
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -238,7 +247,7 @@ fn get_tx_info_v1(
 | 
				
			||||||
    let body = tx.transaction_body.clone();
 | 
					    let body = tx.transaction_body.clone();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if body.reference_inputs.is_some() {
 | 
					    if body.reference_inputs.is_some() {
 | 
				
			||||||
        unreachable!("Reference inputs not allowed in PlutusV1.")
 | 
					        return Err(Error::ScriptAndInputRefNotAllowed);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let inputs = get_tx_in_info_v1(&body.inputs, utxos)?;
 | 
					    let inputs = get_tx_in_info_v1(&body.inputs, utxos)?;
 | 
				
			||||||
| 
						 | 
					@ -375,7 +384,7 @@ fn get_execution_purpose(
 | 
				
			||||||
    utxos: &[ResolvedInput],
 | 
					    utxos: &[ResolvedInput],
 | 
				
			||||||
    script_purpose: &ScriptPurpose,
 | 
					    script_purpose: &ScriptPurpose,
 | 
				
			||||||
    lookup_table: &DataLookupTable,
 | 
					    lookup_table: &DataLookupTable,
 | 
				
			||||||
) -> ExecutionPurpose {
 | 
					) -> Result<ExecutionPurpose, Error> {
 | 
				
			||||||
    match script_purpose {
 | 
					    match script_purpose {
 | 
				
			||||||
        ScriptPurpose::Minting(policy_id) => {
 | 
					        ScriptPurpose::Minting(policy_id) => {
 | 
				
			||||||
            let policy_id_array: [u8; 28] = policy_id.to_vec().try_into().unwrap();
 | 
					            let policy_id_array: [u8; 28] = policy_id.to_vec().try_into().unwrap();
 | 
				
			||||||
| 
						 | 
					@ -383,62 +392,85 @@ fn get_execution_purpose(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let script = match lookup_table.scripts.get(&hash) {
 | 
					            let script = match lookup_table.scripts.get(&hash) {
 | 
				
			||||||
                Some(s) => s.clone(),
 | 
					                Some(s) => s.clone(),
 | 
				
			||||||
                None => unreachable!("Missing required scripts.")
 | 
					                None => {
 | 
				
			||||||
 | 
					                    return Err(Error::MissingRequiredScript {
 | 
				
			||||||
 | 
					                        hash: hash.to_string(),
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            ExecutionPurpose::NoDatum(script)
 | 
					            Ok(ExecutionPurpose::NoDatum(script))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ScriptPurpose::Spending(out_ref) => {
 | 
					        ScriptPurpose::Spending(out_ref) => {
 | 
				
			||||||
            let utxo = utxos.iter().find(|utxo| utxo.input == *out_ref).unwrap();
 | 
					            let utxo = match utxos.iter().find(|utxo| utxo.input == *out_ref) {
 | 
				
			||||||
 | 
					                Some(resolved) => resolved,
 | 
				
			||||||
 | 
					                None => return Err(Error::ResolvedInputNotFound),
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
            match &utxo.output {
 | 
					            match &utxo.output {
 | 
				
			||||||
                TransactionOutput::Legacy(output) => {
 | 
					                TransactionOutput::Legacy(output) => {
 | 
				
			||||||
                    let address = Address::from_bytes(&output.address).unwrap();
 | 
					                    let address = Address::from_bytes(&output.address).unwrap();
 | 
				
			||||||
                    match address {
 | 
					                    match address {
 | 
				
			||||||
                        Address::Shelley(shelley_address) => {
 | 
					                        Address::Shelley(shelley_address) => {
 | 
				
			||||||
                            let script = match lookup_table
 | 
					                            let hash = shelley_address.payment().as_hash();
 | 
				
			||||||
                            .scripts
 | 
					                            let script = match lookup_table.scripts.get(hash) {
 | 
				
			||||||
                            .get(shelley_address.payment().as_hash()) {
 | 
					 | 
				
			||||||
                                Some(s) => s.clone(),
 | 
					                                Some(s) => s.clone(),
 | 
				
			||||||
                                None => unreachable!("Missing required scripts.")
 | 
					                                None => {
 | 
				
			||||||
 | 
					                                    return Err(Error::MissingRequiredScript {
 | 
				
			||||||
 | 
					                                        hash: hash.to_string(),
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            let datum = match lookup_table.datum.get(&output.datum_hash.unwrap_or_else(|| unreachable!("Missing datum hash in input."))) {
 | 
					                            let datum_hash = match &output.datum_hash {
 | 
				
			||||||
 | 
					                                Some(hash) => hash,
 | 
				
			||||||
 | 
					                                None => return Err(Error::MissingRequiredInlineDatumOrHash),
 | 
				
			||||||
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            let datum = match lookup_table.datum.get(datum_hash) {
 | 
				
			||||||
                                Some(d) => d.clone(),
 | 
					                                Some(d) => d.clone(),
 | 
				
			||||||
                                None => unreachable!("Missing datum in witness set.")
 | 
					                                None => {
 | 
				
			||||||
 | 
					                                    return Err(Error::MissingRequiredDatum {
 | 
				
			||||||
 | 
					                                        hash: datum_hash.to_string(),
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            ExecutionPurpose::WithDatum(script, datum)
 | 
					                            Ok(ExecutionPurpose::WithDatum(script, datum))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        _ => unreachable!(
 | 
					                        _ => return Err(Error::ScriptKeyHash),
 | 
				
			||||||
                            "This is impossible. Only shelley addresses can contain a script hash."
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                TransactionOutput::PostAlonzo(output) => {
 | 
					                TransactionOutput::PostAlonzo(output) => {
 | 
				
			||||||
                    let address = Address::from_bytes(&output.address).unwrap();
 | 
					                    let address = Address::from_bytes(&output.address).unwrap();
 | 
				
			||||||
                    match address {
 | 
					                    match address {
 | 
				
			||||||
                        Address::Shelley(shelley_address) => {
 | 
					                        Address::Shelley(shelley_address) => {
 | 
				
			||||||
 | 
					                            let hash = shelley_address.payment().as_hash();
 | 
				
			||||||
                            let script = match lookup_table
 | 
					                            let script = match lookup_table.scripts.get(hash) {
 | 
				
			||||||
                            .scripts
 | 
					 | 
				
			||||||
                            .get(shelley_address.payment().as_hash()) {
 | 
					 | 
				
			||||||
                                Some(s) => s.clone(),
 | 
					                                Some(s) => s.clone(),
 | 
				
			||||||
                                None => unreachable!("Missing required scripts.")
 | 
					                                None => {
 | 
				
			||||||
 | 
					                                    return Err(Error::MissingRequiredScript {
 | 
				
			||||||
 | 
					                                        hash: hash.to_string(),
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
                            let datum = match &output.datum_option {
 | 
					                            let datum = match &output.datum_option {
 | 
				
			||||||
                                Some(DatumOption::Hash(hash)) => {
 | 
					                                Some(DatumOption::Hash(hash)) => {
 | 
				
			||||||
                                    lookup_table.datum.get(hash).unwrap().clone()
 | 
					                                    match lookup_table.datum.get(hash) {
 | 
				
			||||||
 | 
					                                        Some(d) => d.clone(),
 | 
				
			||||||
 | 
					                                        None => {
 | 
				
			||||||
 | 
					                                            return Err(Error::MissingRequiredDatum {
 | 
				
			||||||
 | 
					                                                hash: hash.to_string(),
 | 
				
			||||||
 | 
					                                            })
 | 
				
			||||||
 | 
					                                        }
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                                Some(DatumOption::Data(data)) => data.0.clone(),
 | 
					                                Some(DatumOption::Data(data)) => data.0.clone(),
 | 
				
			||||||
                                _ => unreachable!( "Missing datum hash or inline datum in input."),
 | 
					                                _ => return Err(Error::MissingRequiredInlineDatumOrHash),
 | 
				
			||||||
                            };
 | 
					                            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                            ExecutionPurpose::WithDatum(script, datum)
 | 
					                            Ok(ExecutionPurpose::WithDatum(script, datum))
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        _ => unreachable!(
 | 
					                        _ => return Err(Error::ScriptKeyHash),
 | 
				
			||||||
                            "This is impossible. Only shelley addresses can contain a script hash."
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -446,49 +478,56 @@ fn get_execution_purpose(
 | 
				
			||||||
        ScriptPurpose::Rewarding(stake_credential) => {
 | 
					        ScriptPurpose::Rewarding(stake_credential) => {
 | 
				
			||||||
            let script_hash = match stake_credential {
 | 
					            let script_hash = match stake_credential {
 | 
				
			||||||
                StakeCredential::Scripthash(hash) => *hash,
 | 
					                StakeCredential::Scripthash(hash) => *hash,
 | 
				
			||||||
                _ => unreachable!("This is impossible. A key hash cannot be the hash of a script."),
 | 
					                _ => return Err(Error::ScriptKeyHash),
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let script = match lookup_table.scripts.get(&script_hash) {
 | 
					            let script = match lookup_table.scripts.get(&script_hash) {
 | 
				
			||||||
                Some(s) => s.clone(),
 | 
					                Some(s) => s.clone(),
 | 
				
			||||||
                None => unreachable!("Missing required scripts.")
 | 
					                None => {
 | 
				
			||||||
 | 
					                    return Err(Error::MissingRequiredScript {
 | 
				
			||||||
 | 
					                        hash: script_hash.to_string(),
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ExecutionPurpose::NoDatum(script)
 | 
					            Ok(ExecutionPurpose::NoDatum(script))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        ScriptPurpose::Certifying(cert) => match cert {
 | 
					        ScriptPurpose::Certifying(cert) => match cert {
 | 
				
			||||||
            // StakeRegistration doesn't require a witness from a stake key/script. So I assume it doesn't need to be handled in Plutus either?
 | 
					 | 
				
			||||||
            Certificate::StakeDeregistration(stake_credential) => {
 | 
					            Certificate::StakeDeregistration(stake_credential) => {
 | 
				
			||||||
                let script_hash = match stake_credential {
 | 
					                let script_hash = match stake_credential {
 | 
				
			||||||
                    StakeCredential::Scripthash(hash) => *hash,
 | 
					                    StakeCredential::Scripthash(hash) => *hash,
 | 
				
			||||||
                    _ => unreachable!(
 | 
					                    _ => return Err(Error::ScriptKeyHash),
 | 
				
			||||||
                        "This is impossible. A key hash cannot be the hash of a script."
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let script = match lookup_table.scripts.get(&script_hash) {
 | 
					                let script = match lookup_table.scripts.get(&script_hash) {
 | 
				
			||||||
                    Some(s) => s.clone(),
 | 
					                    Some(s) => s.clone(),
 | 
				
			||||||
                    None => unreachable!("Missing required scripts.")
 | 
					                    None => {
 | 
				
			||||||
 | 
					                        return Err(Error::MissingRequiredScript {
 | 
				
			||||||
 | 
					                            hash: script_hash.to_string(),
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                ExecutionPurpose::NoDatum(script)
 | 
					                Ok(ExecutionPurpose::NoDatum(script))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Certificate::StakeDelegation(stake_credential, _) => {
 | 
					            Certificate::StakeDelegation(stake_credential, _) => {
 | 
				
			||||||
                let script_hash = match stake_credential {
 | 
					                let script_hash = match stake_credential {
 | 
				
			||||||
                    StakeCredential::Scripthash(hash) => *hash,
 | 
					                    StakeCredential::Scripthash(hash) => *hash,
 | 
				
			||||||
                    _ => unreachable!(
 | 
					                    _ => return Err(Error::ScriptKeyHash),
 | 
				
			||||||
                        "This is impossible. A key hash cannot be the hash of a script."
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let script = match lookup_table.scripts.get(&script_hash) {
 | 
					                let script = match lookup_table.scripts.get(&script_hash) {
 | 
				
			||||||
                    Some(s) => s.clone(),
 | 
					                    Some(s) => s.clone(),
 | 
				
			||||||
                    None => unreachable!("Missing required scripts.")
 | 
					                    None => {
 | 
				
			||||||
 | 
					                        return Err(Error::MissingRequiredScript {
 | 
				
			||||||
 | 
					                            hash: script_hash.to_string(),
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                ExecutionPurpose::NoDatum(script)
 | 
					                Ok(ExecutionPurpose::NoDatum(script))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => unreachable!("This is impossible. Only stake deregistration and stake delegation are valid script purposes."),
 | 
					            _ => return Err(Error::OnlyStakeDeregAndDelegAllowed),
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -585,7 +624,7 @@ pub fn eval_redeemer(
 | 
				
			||||||
        &tx.transaction_body.withdrawals,
 | 
					        &tx.transaction_body.withdrawals,
 | 
				
			||||||
    )?;
 | 
					    )?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let execution_purpose: ExecutionPurpose = get_execution_purpose(utxos, &purpose, lookup_table);
 | 
					    let execution_purpose: ExecutionPurpose = get_execution_purpose(utxos, &purpose, lookup_table)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    match execution_purpose {
 | 
					    match execution_purpose {
 | 
				
			||||||
        ExecutionPurpose::WithDatum(script_version, datum) => match script_version {
 | 
					        ExecutionPurpose::WithDatum(script_version, datum) => match script_version {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue