Fix script context translations for withdrawals and validity intervals.
This commit is contained in:
@@ -9,7 +9,7 @@ use std::{fmt, fs, path::PathBuf, process};
|
||||
use uplc::{
|
||||
machine::cost_model::ExBudget,
|
||||
tx::{
|
||||
self,
|
||||
self, redeemer_tag_to_string,
|
||||
script_context::{ResolvedInput, SlotConfig},
|
||||
},
|
||||
};
|
||||
@@ -110,11 +110,11 @@ pub fn exec(
|
||||
|
||||
let with_redeemer = |redeemer: &Redeemer| {
|
||||
eprintln!(
|
||||
"{} {:?}[{}]",
|
||||
"{} {}[{}]",
|
||||
" Evaluating"
|
||||
.if_supports_color(Stderr, |s| s.purple())
|
||||
.if_supports_color(Stderr, |s| s.bold()),
|
||||
redeemer.tag,
|
||||
redeemer_tag_to_string(&redeemer.tag),
|
||||
redeemer.index
|
||||
)
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@ pub use pallas_primitives::{
|
||||
babbage::{PostAlonzoTransactionOutput, TransactionInput, TransactionOutput, Value},
|
||||
Error, Fragment,
|
||||
};
|
||||
pub use tx::redeemer_tag_to_string;
|
||||
|
||||
pub fn plutus_data(bytes: &[u8]) -> Result<PlutusData, Error> {
|
||||
PlutusData::decode_fragment(bytes)
|
||||
|
||||
@@ -13,9 +13,19 @@ pub enum Error {
|
||||
OpenTermEvaluated(Term<NamedDeBruijn>),
|
||||
#[error("The validator crashed / exited prematurely")]
|
||||
EvaluationFailure,
|
||||
#[error("Attempted to instantiate a non-polymorphic term:\n\n{0:#?}")]
|
||||
#[error(
|
||||
"Attempted to instantiate a non-polymorphic term\n{:>13} {}",
|
||||
"Term",
|
||||
indent(redacted(format!("{:#?}", .0), 10)),
|
||||
)]
|
||||
NonPolymorphicInstantiation(Value),
|
||||
#[error("Attempted to apply a non-function:\n\n{0:#?} to argument:\n\n{1:#?}")]
|
||||
#[error(
|
||||
"Attempted to apply an argument to a non-function\n{:>13} {}\n{:>13} {}",
|
||||
"Thing",
|
||||
indent(redacted(format!("{:#?}", .0), 5)),
|
||||
"Argument",
|
||||
indent(redacted(format!("{:#?}", .1), 5)),
|
||||
)]
|
||||
NonFunctionalApplication(Value, Value),
|
||||
#[error("Attempted to case a non-const:\n\n{0:#?}")]
|
||||
NonConstrScrutinized(Value),
|
||||
@@ -61,7 +71,10 @@ pub enum Error {
|
||||
UnexpectedEd25519PublicKeyLength(usize),
|
||||
#[error("Ed25519S Signature should be 64 bytes but it was {0}")]
|
||||
UnexpectedEd25519SignatureLength(usize),
|
||||
#[error("Failed to deserialise PlutusData using {0}:\n\n{1:#?}")]
|
||||
#[error(
|
||||
"Failed to deserialise PlutusData using {0}:\n\n{}",
|
||||
redacted(format!("{:#?}", .1), 10),
|
||||
)]
|
||||
DeserialisationError(String, Value),
|
||||
#[error("Integer overflow")]
|
||||
OverflowError,
|
||||
@@ -83,3 +96,21 @@ impl From<k256::ecdsa::Error> for Error {
|
||||
Error::K256Error(format!("K256 error: {}", error))
|
||||
}
|
||||
}
|
||||
|
||||
/// Print only the first n lines of possibly long output, and redact the rest if longer.
|
||||
fn redacted(s: String, max_rows: usize) -> String {
|
||||
let rows = s.lines();
|
||||
|
||||
if rows.count() > max_rows {
|
||||
let last_line = s.lines().last().unwrap();
|
||||
let mut s = s.lines().take(max_rows).collect::<Vec<_>>().join("\n");
|
||||
s.push_str(&format!("\n ...redacted...\n{last_line}"));
|
||||
s
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn indent(s: String) -> String {
|
||||
s.lines().collect::<Vec<_>>().join(&format!("\n{:>14}", ""))
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use pallas_primitives::{
|
||||
Fragment,
|
||||
};
|
||||
use pallas_traverse::{Era, MultiEraTx};
|
||||
pub use phase_one::eval_phase_one;
|
||||
pub use phase_one::{eval_phase_one, redeemer_tag_to_string};
|
||||
pub use script_context::{DataLookupTable, ResolvedInput, SlotConfig};
|
||||
|
||||
pub mod error;
|
||||
|
||||
@@ -99,4 +99,6 @@ pub enum Error {
|
||||
MissingScriptForRedeemer,
|
||||
#[error("failed to apply parameters to Plutus script")]
|
||||
ApplyParamsError,
|
||||
#[error("validity start or end too far in the past")]
|
||||
SlotTooFarInThePast { oldest_allowed: u64 },
|
||||
}
|
||||
|
||||
@@ -4,15 +4,16 @@ use super::{
|
||||
Error,
|
||||
};
|
||||
use crate::{
|
||||
ast::{Data, FakeNamedDeBruijn, NamedDeBruijn, Program},
|
||||
ast::{FakeNamedDeBruijn, NamedDeBruijn, Program},
|
||||
machine::cost_model::ExBudget,
|
||||
tx::script_context::{DataLookupTable, ScriptVersion, TxInfoV1, TxInfoV2, TxInfoV3},
|
||||
tx::{
|
||||
phase_one::redeemer_tag_to_string,
|
||||
script_context::{DataLookupTable, ScriptVersion, TxInfoV1, TxInfoV2, TxInfoV3},
|
||||
},
|
||||
PlutusData,
|
||||
};
|
||||
use pallas_codec::utils::Bytes;
|
||||
use pallas_primitives::conway::{
|
||||
CostMdls, CostModel, ExUnits, Language, MintedTx, Redeemer, RedeemerTag,
|
||||
};
|
||||
use pallas_primitives::conway::{CostMdls, CostModel, ExUnits, Language, MintedTx, Redeemer};
|
||||
|
||||
pub fn eval_redeemer(
|
||||
tx: &MintedTx,
|
||||
@@ -44,21 +45,16 @@ pub fn eval_redeemer(
|
||||
}
|
||||
.apply_data(redeemer.data.clone())
|
||||
.apply_data(script_context.to_plutus_data()),
|
||||
ScriptContext::V3 { .. } if datum.is_some() => {
|
||||
|
||||
// FIXME: Temporary, but needed until https://github.com/aiken-lang/aiken/pull/977
|
||||
// is implemented.
|
||||
ScriptContext::V3 { .. } => if let Some(datum) = datum {
|
||||
program.apply_data(datum)
|
||||
} else {
|
||||
program
|
||||
// FIXME: Temporary, but needed until https://github.com/aiken-lang/aiken/pull/977
|
||||
// is implemented.
|
||||
.apply_data(Data::constr(0, vec![]))
|
||||
.apply_data(Data::constr(0, vec![]))
|
||||
.apply_data(script_context.to_plutus_data())
|
||||
}
|
||||
ScriptContext::V3 { .. } => {
|
||||
program
|
||||
// FIXME: Temporary, but needed until https://github.com/aiken-lang/aiken/pull/977
|
||||
// is implemented.
|
||||
.apply_data(Data::constr(0, vec![]))
|
||||
.apply_data(script_context.to_plutus_data())
|
||||
}
|
||||
.apply_data(redeemer.data.clone())
|
||||
.apply_data(script_context.to_plutus_data()),
|
||||
};
|
||||
|
||||
let mut eval_result = if let Some(costs) = cost_mdl_opt {
|
||||
@@ -154,15 +150,3 @@ pub fn eval_redeemer(
|
||||
err: Box::new(err),
|
||||
})
|
||||
}
|
||||
|
||||
fn redeemer_tag_to_string(redeemer_tag: &RedeemerTag) -> String {
|
||||
match redeemer_tag {
|
||||
RedeemerTag::Spend => "Spend",
|
||||
RedeemerTag::Mint => "Mint",
|
||||
RedeemerTag::Reward => "Withdraw",
|
||||
RedeemerTag::Cert => "Publish",
|
||||
RedeemerTag::Propose => "Propose",
|
||||
RedeemerTag::Vote => "Vote",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use super::{
|
||||
error::Error,
|
||||
script_context::{sort_voters, DataLookupTable, ResolvedInput, ScriptPurpose, ScriptVersion},
|
||||
};
|
||||
use crate::tx::script_context::sort_reward_accounts;
|
||||
use itertools::Itertools;
|
||||
use pallas_addresses::{Address, ScriptHash, ShelleyPaymentPart, StakePayload};
|
||||
use pallas_codec::utils::Nullable;
|
||||
@@ -234,13 +235,20 @@ pub fn has_exact_set_of_redeemers(
|
||||
let missing: Vec<_> = redeemers_needed
|
||||
.into_iter()
|
||||
.filter(|x| !wits_redeemer_keys.contains(&&x.0))
|
||||
.map(|x| format!("{:?}[{:?}] -> {}", x.0.tag, x.0.index, x.2))
|
||||
.map(|x| {
|
||||
format!(
|
||||
"{}[{:?}] -> {}",
|
||||
redeemer_tag_to_string(&x.0.tag),
|
||||
x.0.index,
|
||||
x.2
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let extra: Vec<_> = wits_redeemer_keys
|
||||
.into_iter()
|
||||
.filter(|x| !needed_redeemer_keys.contains(x))
|
||||
.map(|x| format!("{:?}[{:?}]", x.tag, x.index))
|
||||
.map(|x| format!("{}[{:?}]", redeemer_tag_to_string(&x.tag), x.index))
|
||||
.collect();
|
||||
|
||||
if !missing.is_empty() || !extra.is_empty() {
|
||||
@@ -306,7 +314,7 @@ fn build_redeemer_key(
|
||||
.map(|m| m.iter().map(|(acnt, _)| acnt).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
reward_accounts.sort();
|
||||
reward_accounts.sort_by(|acnt_a, acnt_b| sort_reward_accounts(acnt_a, acnt_b));
|
||||
|
||||
let mut redeemer_key = None;
|
||||
|
||||
@@ -377,3 +385,15 @@ fn build_redeemer_key(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn redeemer_tag_to_string(redeemer_tag: &RedeemerTag) -> String {
|
||||
match redeemer_tag {
|
||||
RedeemerTag::Spend => "Spend",
|
||||
RedeemerTag::Mint => "Mint",
|
||||
RedeemerTag::Reward => "Withdraw",
|
||||
RedeemerTag::Cert => "Publish",
|
||||
RedeemerTag::Propose => "Propose",
|
||||
RedeemerTag::Vote => "Vote",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::{to_plutus_data::MintValue, Error};
|
||||
use itertools::Itertools;
|
||||
use pallas_addresses::{Address, StakePayload};
|
||||
use pallas_addresses::{Address, Network, StakePayload};
|
||||
use pallas_codec::utils::{
|
||||
KeyValuePairs, NonEmptyKeyValuePairs, NonEmptySet, Nullable, PositiveCoin,
|
||||
Bytes, KeyValuePairs, NonEmptyKeyValuePairs, NonEmptySet, Nullable, PositiveCoin,
|
||||
};
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::{
|
||||
@@ -217,7 +217,7 @@ impl TxInfoV1 {
|
||||
let inputs = get_tx_in_info_v1(&tx.transaction_body.inputs, utxos)?;
|
||||
let certificates = get_certificates_info(&tx.transaction_body.certificates);
|
||||
let withdrawals =
|
||||
KeyValuePairs::from(get_withdrawal_info(&tx.transaction_body.withdrawals));
|
||||
KeyValuePairs::from(get_withdrawals_info(&tx.transaction_body.withdrawals));
|
||||
let mint = get_mint_info(&tx.transaction_body.mint);
|
||||
|
||||
let redeemers = get_redeemers_info(
|
||||
@@ -232,7 +232,7 @@ impl TxInfoV1 {
|
||||
mint,
|
||||
certificates,
|
||||
withdrawals: withdrawals.into(),
|
||||
valid_range: get_validity_range_info(&tx.transaction_body, slot_config),
|
||||
valid_range: get_validity_range_info(&tx.transaction_body, slot_config)?,
|
||||
signatories: get_signatories_info(&tx.transaction_body.required_signers),
|
||||
data: get_data_info(&tx.transaction_witness_set),
|
||||
redeemers,
|
||||
@@ -266,7 +266,7 @@ impl TxInfoV2 {
|
||||
let inputs = get_tx_in_info_v2(&tx.transaction_body.inputs, utxos)?;
|
||||
let certificates = get_certificates_info(&tx.transaction_body.certificates);
|
||||
let withdrawals =
|
||||
KeyValuePairs::from(get_withdrawal_info(&tx.transaction_body.withdrawals));
|
||||
KeyValuePairs::from(get_withdrawals_info(&tx.transaction_body.withdrawals));
|
||||
let mint = get_mint_info(&tx.transaction_body.mint);
|
||||
|
||||
let redeemers = get_redeemers_info(
|
||||
@@ -290,7 +290,7 @@ impl TxInfoV2 {
|
||||
mint,
|
||||
certificates,
|
||||
withdrawals,
|
||||
valid_range: get_validity_range_info(&tx.transaction_body, slot_config),
|
||||
valid_range: get_validity_range_info(&tx.transaction_body, slot_config)?,
|
||||
signatories: get_signatories_info(&tx.transaction_body.required_signers),
|
||||
data: KeyValuePairs::from(get_data_info(&tx.transaction_witness_set)),
|
||||
redeemers,
|
||||
@@ -330,7 +330,7 @@ impl TxInfoV3 {
|
||||
let certificates = get_certificates_info(&tx.transaction_body.certificates);
|
||||
|
||||
let withdrawals =
|
||||
KeyValuePairs::from(get_withdrawal_info(&tx.transaction_body.withdrawals));
|
||||
KeyValuePairs::from(get_withdrawals_info(&tx.transaction_body.withdrawals));
|
||||
|
||||
let mint = get_mint_info(&tx.transaction_body.mint);
|
||||
|
||||
@@ -367,7 +367,7 @@ impl TxInfoV3 {
|
||||
mint,
|
||||
certificates,
|
||||
withdrawals,
|
||||
valid_range: get_validity_range_info(&tx.transaction_body, slot_config),
|
||||
valid_range: get_validity_range_info(&tx.transaction_body, slot_config)?,
|
||||
signatories: get_signatories_info(&tx.transaction_body.required_signers),
|
||||
data: KeyValuePairs::from(get_data_info(&tx.transaction_witness_set)),
|
||||
redeemers,
|
||||
@@ -626,14 +626,14 @@ pub fn get_proposal_procedures_info(
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn get_withdrawal_info(
|
||||
pub fn get_withdrawals_info(
|
||||
withdrawals: &Option<NonEmptyKeyValuePairs<RewardAccount, Coin>>,
|
||||
) -> Vec<(Address, Coin)> {
|
||||
withdrawals
|
||||
.clone()
|
||||
.map(|w| {
|
||||
w.into_iter()
|
||||
.sorted()
|
||||
.sorted_by(|(accnt_a, _), (accnt_b, _)| sort_reward_accounts(accnt_a, accnt_b))
|
||||
.map(|(reward_account, coin)| (Address::from_bytes(&reward_account).unwrap(), coin))
|
||||
.collect()
|
||||
})
|
||||
@@ -643,21 +643,31 @@ pub fn get_withdrawal_info(
|
||||
pub fn get_validity_range_info(
|
||||
body: &MintedTransactionBody,
|
||||
slot_config: &SlotConfig,
|
||||
) -> TimeRange {
|
||||
fn slot_to_begin_posix_time(slot: u64, sc: &SlotConfig) -> u64 {
|
||||
) -> Result<TimeRange, Error> {
|
||||
fn slot_to_begin_posix_time(slot: u64, sc: &SlotConfig) -> Result<u64, Error> {
|
||||
if slot < sc.zero_slot {
|
||||
return Err(Error::SlotTooFarInThePast {
|
||||
oldest_allowed: sc.zero_slot,
|
||||
});
|
||||
}
|
||||
let ms_after_begin = (slot - sc.zero_slot) * sc.slot_length as u64;
|
||||
sc.zero_time + ms_after_begin
|
||||
Ok(sc.zero_time + ms_after_begin)
|
||||
}
|
||||
|
||||
fn slot_range_to_posix_time_range(slot_range: TimeRange, sc: &SlotConfig) -> TimeRange {
|
||||
TimeRange {
|
||||
fn slot_range_to_posix_time_range(
|
||||
slot_range: TimeRange,
|
||||
sc: &SlotConfig,
|
||||
) -> Result<TimeRange, Error> {
|
||||
Ok(TimeRange {
|
||||
lower_bound: slot_range
|
||||
.lower_bound
|
||||
.map(|lower_bound| slot_to_begin_posix_time(lower_bound, sc)),
|
||||
.map(|lower_bound| slot_to_begin_posix_time(lower_bound, sc))
|
||||
.transpose()?,
|
||||
upper_bound: slot_range
|
||||
.upper_bound
|
||||
.map(|upper_bound| slot_to_begin_posix_time(upper_bound, sc)),
|
||||
}
|
||||
.map(|upper_bound| slot_to_begin_posix_time(upper_bound, sc))
|
||||
.transpose()?,
|
||||
})
|
||||
}
|
||||
|
||||
slot_range_to_posix_time_range(
|
||||
@@ -841,7 +851,7 @@ pub fn find_script(
|
||||
lookup_script(&hash)
|
||||
}),
|
||||
|
||||
RedeemerTag::Reward => get_withdrawal_info(&tx.transaction_body.withdrawals)
|
||||
RedeemerTag::Reward => get_withdrawals_info(&tx.transaction_body.withdrawals)
|
||||
.get(redeemer.index as usize)
|
||||
.ok_or(Error::MissingScriptForRedeemer)
|
||||
.and_then(|(addr, _)| {
|
||||
@@ -1086,6 +1096,34 @@ fn sort_gov_action_id(a: &GovActionId, b: &GovActionId) -> Ordering {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sort_reward_accounts(a: &Bytes, b: &Bytes) -> Ordering {
|
||||
let addr_a = Address::from_bytes(a).expect("invalid reward address in withdrawals.");
|
||||
let addr_b = Address::from_bytes(b).expect("invalid reward address in withdrawals.");
|
||||
|
||||
fn network_tag(network: Network) -> u8 {
|
||||
match network {
|
||||
Network::Testnet => 0,
|
||||
Network::Mainnet => 1,
|
||||
Network::Other(tag) => tag,
|
||||
}
|
||||
}
|
||||
|
||||
if let (Address::Stake(accnt_a), Address::Stake(accnt_b)) = (addr_a, addr_b) {
|
||||
if accnt_a.network() != accnt_b.network() {
|
||||
return network_tag(accnt_a.network()).cmp(&network_tag(accnt_b.network()));
|
||||
}
|
||||
|
||||
match (accnt_a.payload(), accnt_b.payload()) {
|
||||
(StakePayload::Script(..), StakePayload::Stake(..)) => Ordering::Less,
|
||||
(StakePayload::Stake(..), StakePayload::Script(..)) => Ordering::Greater,
|
||||
(StakePayload::Script(hash_a), StakePayload::Script(hash_b)) => hash_a.cmp(hash_b),
|
||||
(StakePayload::Stake(hash_a), StakePayload::Stake(hash_b)) => hash_a.cmp(hash_b),
|
||||
}
|
||||
} else {
|
||||
unreachable!("invalid reward address in withdrawals.");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
@@ -1479,4 +1517,62 @@ mod tests {
|
||||
// from the Haskell ledger / cardano node.
|
||||
insta::assert_debug_snapshot!(script_context.to_plutus_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn script_context_withdraw() {
|
||||
let redeemer = Redeemer {
|
||||
tag: RedeemerTag::Reward,
|
||||
index: 0,
|
||||
data: Data::constr(0, vec![]),
|
||||
ex_units: ExUnits {
|
||||
mem: 1000000,
|
||||
steps: 100000000,
|
||||
},
|
||||
};
|
||||
|
||||
// NOTE: The transaction also contains treasury donation and current treasury amount
|
||||
let script_context = fixture_tx_info(
|
||||
"84a7008182582000000000000000000000000000000000000000000000000000\
|
||||
00000000000000000183a2005839200000000000000000000000000000000000\
|
||||
0000000000000000000000111111111111111111111111111111111111111111\
|
||||
11111111111111011a000f4240a2005823400000000000000000000000000000\
|
||||
00000000000000000000000000008198bd431b03011a000f4240a20058235011\
|
||||
1111111111111111111111111111111111111111111111111111118198bd431b\
|
||||
03011a000f424002182a031a00448e0105a1581df004036eecadc2f19e95f831\
|
||||
b4bc08919cde1d1088d74602bd3dcd78a2000e81581c00000000000000000000\
|
||||
0000000000000000000000000000000000001601a10582840000d87a81d87980\
|
||||
821a000f42401a05f5e100840300d87980821a000f42401a05f5e100f5f6",
|
||||
"8182582000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000",
|
||||
"81a40058393004036eecadc2f19e95f831b4bc08919cde1d1088d74602bd3dcd\
|
||||
78a204036eecadc2f19e95f831b4bc08919cde1d1088d74602bd3dcd78a2011a\
|
||||
000f4240028201d81843d8798003d818590221820359021c5902190101003232\
|
||||
323232323232322232533333300c00215323330073001300937540062a660109\
|
||||
211c52756e6e696e672032206172672076616c696461746f72206d696e740013\
|
||||
533333300d004153330073001300937540082a66601660146ea8010494ccc021\
|
||||
288a4c2a660129211856616c696461746f722072657475726e65642066616c73\
|
||||
65001365600600600600600600600315330084911d52756e6e696e6720332061\
|
||||
72672076616c696461746f72207370656e640013533333300d00415333007300\
|
||||
1300937540082a66601660146ea8010494cccccc03800454ccc020c008c028dd\
|
||||
50008a99980618059baa0011253330094a22930a998052491856616c69646174\
|
||||
6f722072657475726e65642066616c7365001365600600600600600600600600\
|
||||
6006006006006300c300a37540066e1d20001533007001161533007001161533\
|
||||
00700116153300700116490191496e636f72726563742072656465656d657220\
|
||||
7479706520666f722076616c696461746f72207370656e642e0a202020202020\
|
||||
2020202020202020202020202020446f75626c6520636865636b20796f752068\
|
||||
6176652077726170706564207468652072656465656d65722074797065206173\
|
||||
2073706563696669656420696e20796f757220706c757475732e6a736f6e0015\
|
||||
330034910b5f746d70313a20566f6964001615330024910b5f746d70303a2056\
|
||||
6f696400165734ae7155ceaab9e5573eae855d21",
|
||||
)
|
||||
.into_script_context(&redeemer, None)
|
||||
.unwrap();
|
||||
|
||||
// NOTE: The initial snapshot has been generated using the Haskell
|
||||
// implementation of the ledger library for that same serialized
|
||||
// transactions. It is meant to control that our construction of the
|
||||
// script context and its serialization matches exactly those
|
||||
// from the Haskell ledger / cardano node.
|
||||
insta::assert_debug_snapshot!(script_context.to_plutus_data());
|
||||
}
|
||||
}
|
||||
|
||||
1236
crates/uplc/src/tx/snapshots/uplc__tx__script_context__tests__script_context_withdraw.snap
vendored
Normal file
1236
crates/uplc/src/tx/snapshots/uplc__tx__script_context__tests__script_context_withdraw.snap
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -736,127 +736,34 @@ impl ToPlutusData for PlutusData {
|
||||
|
||||
impl ToPlutusData for TimeRange {
|
||||
fn to_plutus_data(&self) -> PlutusData {
|
||||
match &self {
|
||||
TimeRange {
|
||||
lower_bound: Some(lower_bound),
|
||||
upper_bound: None,
|
||||
} => {
|
||||
wrap_multiple_with_constr(
|
||||
fn bound(bound: Option<u64>, is_lower: bool) -> PlutusData {
|
||||
match bound {
|
||||
Some(x) => wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// LowerBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// Finite
|
||||
wrap_with_constr(1, lower_bound.to_plutus_data()),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
), //UpperBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// PosInf
|
||||
empty_constr(2),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
wrap_with_constr(1, x.to_plutus_data()),
|
||||
// NOTE: Finite lower bounds are always inclusive, unlike upper bounds.
|
||||
is_lower.to_plutus_data(),
|
||||
],
|
||||
)
|
||||
}
|
||||
TimeRange {
|
||||
lower_bound: None,
|
||||
upper_bound: Some(upper_bound),
|
||||
} => {
|
||||
wrap_multiple_with_constr(
|
||||
),
|
||||
None => wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// LowerBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// NegInf
|
||||
empty_constr(0),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
//UpperBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// Finite
|
||||
wrap_with_constr(1, upper_bound.to_plutus_data()),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
empty_constr(if is_lower { 0 } else { 2 }),
|
||||
// NOTE: Infinite bounds are always exclusive, by convention.
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
)
|
||||
}
|
||||
TimeRange {
|
||||
lower_bound: Some(lower_bound),
|
||||
upper_bound: Some(upper_bound),
|
||||
} => {
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// LowerBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// Finite
|
||||
wrap_with_constr(1, lower_bound.to_plutus_data()),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
//UpperBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// Finite
|
||||
wrap_with_constr(1, upper_bound.to_plutus_data()),
|
||||
// Closure
|
||||
false.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
}
|
||||
TimeRange {
|
||||
lower_bound: None,
|
||||
upper_bound: None,
|
||||
} => {
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// LowerBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// NegInf
|
||||
empty_constr(0),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
//UpperBound
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
// PosInf
|
||||
empty_constr(2),
|
||||
// Closure
|
||||
true.to_plutus_data(),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
wrap_multiple_with_constr(
|
||||
0,
|
||||
vec![
|
||||
bound(self.lower_bound, true),
|
||||
bound(self.upper_bound, false),
|
||||
],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user