fix: Provide original hash for inline datum (#221)
This commit is contained in:
parent
9d8ca617ef
commit
e600190107
8 changed files with 216 additions and 110 deletions
|
|
@ -98,8 +98,8 @@ where
|
||||||
|
|
||||||
impl<'b, C, K, V> minicbor::decode::Decode<'b, C> for KeyValuePairs<K, V>
|
impl<'b, C, K, V> minicbor::decode::Decode<'b, C> for KeyValuePairs<K, V>
|
||||||
where
|
where
|
||||||
K: Encode<C> + Decode<'b, C> + Clone,
|
K: Decode<'b, C> + Clone,
|
||||||
V: Encode<C> + Decode<'b, C> + Clone,
|
V: Decode<'b, C> + Clone,
|
||||||
{
|
{
|
||||||
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||||
let datatype = d.datatype()?;
|
let datatype = d.datatype()?;
|
||||||
|
|
@ -153,7 +153,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct that maintains a reference to whether a cbor array was indef or not
|
/// A struct that maintains a reference to whether a cbor array was indef or not
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||||
pub enum MaybeIndefArray<A> {
|
pub enum MaybeIndefArray<A> {
|
||||||
Def(Vec<A>),
|
Def(Vec<A>),
|
||||||
Indef(Vec<A>),
|
Indef(Vec<A>),
|
||||||
|
|
@ -290,6 +290,12 @@ where
|
||||||
#[serde(transparent)]
|
#[serde(transparent)]
|
||||||
pub struct CborWrap<T>(pub T);
|
pub struct CborWrap<T>(pub T);
|
||||||
|
|
||||||
|
impl<T> CborWrap<T> {
|
||||||
|
pub fn unwrap(self) -> T {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'b, C, T> minicbor::Decode<'b, C> for CborWrap<T>
|
impl<'b, C, T> minicbor::Decode<'b, C> for CborWrap<T>
|
||||||
where
|
where
|
||||||
T: minicbor::Decode<'b, C>,
|
T: minicbor::Decode<'b, C>,
|
||||||
|
|
|
||||||
|
|
@ -230,14 +230,14 @@ pub struct Update {
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(map)]
|
#[cbor(map)]
|
||||||
pub struct TransactionBody {
|
pub struct PseudoTransactionBody<T1> {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub inputs: Vec<TransactionInput>,
|
pub inputs: Vec<TransactionInput>,
|
||||||
|
|
||||||
#[n(1)]
|
#[n(1)]
|
||||||
pub outputs: Vec<TransactionOutput>,
|
pub outputs: Vec<T1>,
|
||||||
|
|
||||||
#[n(2)]
|
#[n(2)]
|
||||||
pub fee: u64,
|
pub fee: u64,
|
||||||
|
|
@ -276,7 +276,7 @@ pub struct TransactionBody {
|
||||||
pub network_id: Option<NetworkId>,
|
pub network_id: Option<NetworkId>,
|
||||||
|
|
||||||
#[n(16)]
|
#[n(16)]
|
||||||
pub collateral_return: Option<TransactionOutput>,
|
pub collateral_return: Option<T1>,
|
||||||
|
|
||||||
#[n(17)]
|
#[n(17)]
|
||||||
pub total_collateral: Option<Coin>,
|
pub total_collateral: Option<Coin>,
|
||||||
|
|
@ -285,23 +285,51 @@ pub struct TransactionBody {
|
||||||
pub reference_inputs: Option<Vec<TransactionInput>>,
|
pub reference_inputs: Option<Vec<TransactionInput>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
pub type TransactionBody = PseudoTransactionBody<TransactionOutput>;
|
||||||
pub enum TransactionOutput {
|
|
||||||
Legacy(LegacyTransactionOutput),
|
pub type MintedTransactionBody<'a> = PseudoTransactionBody<MintedTransactionOutput<'a>>;
|
||||||
PostAlonzo(PostAlonzoTransactionOutput),
|
|
||||||
|
impl<'a> From<MintedTransactionBody<'a>> for TransactionBody {
|
||||||
|
fn from(value: MintedTransactionBody<'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
inputs: value.inputs,
|
||||||
|
outputs: value.outputs.into_iter().map(|x| x.into()).collect(),
|
||||||
|
fee: value.fee,
|
||||||
|
ttl: value.ttl,
|
||||||
|
certificates: value.certificates,
|
||||||
|
withdrawals: value.withdrawals,
|
||||||
|
update: value.update,
|
||||||
|
auxiliary_data_hash: value.auxiliary_data_hash,
|
||||||
|
validity_interval_start: value.validity_interval_start,
|
||||||
|
mint: value.mint,
|
||||||
|
script_data_hash: value.script_data_hash,
|
||||||
|
collateral: value.collateral,
|
||||||
|
required_signers: value.required_signers,
|
||||||
|
network_id: value.network_id,
|
||||||
|
collateral_return: value.collateral_return.map(|x| x.into()),
|
||||||
|
total_collateral: value.total_collateral,
|
||||||
|
reference_inputs: value.reference_inputs,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, C> minicbor::Decode<'b, C> for TransactionOutput {
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
fn decode(
|
pub enum PseudoTransactionOutput<T> {
|
||||||
d: &mut minicbor::Decoder<'b>,
|
Legacy(LegacyTransactionOutput),
|
||||||
_ctx: &mut C,
|
PostAlonzo(T),
|
||||||
) -> Result<Self, minicbor::decode::Error> {
|
}
|
||||||
|
|
||||||
|
impl<'b, C, T> minicbor::Decode<'b, C> for PseudoTransactionOutput<T>
|
||||||
|
where
|
||||||
|
T: minicbor::Decode<'b, C>,
|
||||||
|
{
|
||||||
|
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||||
match d.datatype()? {
|
match d.datatype()? {
|
||||||
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
|
minicbor::data::Type::Array | minicbor::data::Type::ArrayIndef => {
|
||||||
Ok(TransactionOutput::Legacy(d.decode()?))
|
Ok(PseudoTransactionOutput::Legacy(d.decode_with(ctx)?))
|
||||||
}
|
}
|
||||||
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
|
minicbor::data::Type::Map | minicbor::data::Type::MapIndef => {
|
||||||
Ok(TransactionOutput::PostAlonzo(d.decode()?))
|
Ok(PseudoTransactionOutput::PostAlonzo(d.decode_with(ctx)?))
|
||||||
}
|
}
|
||||||
_ => Err(minicbor::decode::Error::message(
|
_ => Err(minicbor::decode::Error::message(
|
||||||
"invalid type for transaction output struct",
|
"invalid type for transaction output struct",
|
||||||
|
|
@ -310,22 +338,39 @@ impl<'b, C> minicbor::Decode<'b, C> for TransactionOutput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> minicbor::Encode<C> for TransactionOutput {
|
impl<C, T> minicbor::Encode<C> for PseudoTransactionOutput<T>
|
||||||
|
where
|
||||||
|
T: minicbor::Encode<C>,
|
||||||
|
{
|
||||||
fn encode<W: minicbor::encode::Write>(
|
fn encode<W: minicbor::encode::Write>(
|
||||||
&self,
|
&self,
|
||||||
e: &mut minicbor::Encoder<W>,
|
e: &mut minicbor::Encoder<W>,
|
||||||
ctx: &mut C,
|
ctx: &mut C,
|
||||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||||
match self {
|
match self {
|
||||||
TransactionOutput::Legacy(x) => x.encode(e, ctx),
|
PseudoTransactionOutput::Legacy(x) => x.encode(e, ctx),
|
||||||
TransactionOutput::PostAlonzo(x) => x.encode(e, ctx),
|
PseudoTransactionOutput::PostAlonzo(x) => x.encode(e, ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
|
pub type TransactionOutput = PseudoTransactionOutput<PostAlonzoTransactionOutput>;
|
||||||
|
|
||||||
|
pub type MintedTransactionOutput<'b> =
|
||||||
|
PseudoTransactionOutput<MintedPostAlonzoTransactionOutput<'b>>;
|
||||||
|
|
||||||
|
impl<'b> From<MintedTransactionOutput<'b>> for TransactionOutput {
|
||||||
|
fn from(value: MintedTransactionOutput<'b>) -> Self {
|
||||||
|
match value {
|
||||||
|
PseudoTransactionOutput::Legacy(x) => Self::Legacy(x),
|
||||||
|
PseudoTransactionOutput::PostAlonzo(x) => Self::PostAlonzo(x.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
#[cbor(map)]
|
#[cbor(map)]
|
||||||
pub struct PostAlonzoTransactionOutput {
|
pub struct PseudoPostAlonzoTransactionOutput<T1> {
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub address: Bytes,
|
pub address: Bytes,
|
||||||
|
|
||||||
|
|
@ -333,12 +378,28 @@ pub struct PostAlonzoTransactionOutput {
|
||||||
pub value: Value,
|
pub value: Value,
|
||||||
|
|
||||||
#[n(2)]
|
#[n(2)]
|
||||||
pub datum_option: Option<DatumOption>,
|
pub datum_option: Option<T1>,
|
||||||
|
|
||||||
#[n(3)]
|
#[n(3)]
|
||||||
pub script_ref: Option<ScriptRef>,
|
pub script_ref: Option<ScriptRef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type PostAlonzoTransactionOutput = PseudoPostAlonzoTransactionOutput<DatumOption>;
|
||||||
|
|
||||||
|
pub type MintedPostAlonzoTransactionOutput<'b> =
|
||||||
|
PseudoPostAlonzoTransactionOutput<MintedDatumOption<'b>>;
|
||||||
|
|
||||||
|
impl<'b> From<MintedPostAlonzoTransactionOutput<'b>> for PostAlonzoTransactionOutput {
|
||||||
|
fn from(value: MintedPostAlonzoTransactionOutput<'b>) -> Self {
|
||||||
|
Self {
|
||||||
|
address: value.address,
|
||||||
|
value: value.value,
|
||||||
|
datum_option: value.datum_option.map(|x| x.into()),
|
||||||
|
script_ref: value.script_ref,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub use crate::alonzo::VKeyWitness;
|
pub use crate::alonzo::VKeyWitness;
|
||||||
|
|
||||||
pub use crate::alonzo::NativeScript;
|
pub use crate::alonzo::NativeScript;
|
||||||
|
|
@ -455,25 +516,25 @@ pub struct PostAlonzoAuxiliaryData {
|
||||||
|
|
||||||
pub type DatumHash = Hash<32>;
|
pub type DatumHash = Hash<32>;
|
||||||
|
|
||||||
pub type Data = CborWrap<PlutusData>;
|
//pub type Data = CborWrap<PlutusData>;
|
||||||
|
|
||||||
// datum_option = [ 0, $hash32 // 1, data ]
|
// datum_option = [ 0, $hash32 // 1, data ]
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum DatumOption {
|
pub enum PseudoDatumOption<T1> {
|
||||||
Hash(Hash<32>),
|
Hash(Hash<32>),
|
||||||
Data(Data),
|
Data(CborWrap<T1>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, C> minicbor::Decode<'b, C> for DatumOption {
|
impl<'b, C, T> minicbor::Decode<'b, C> for PseudoDatumOption<T>
|
||||||
fn decode(
|
where
|
||||||
d: &mut minicbor::Decoder<'b>,
|
T: minicbor::Decode<'b, C>,
|
||||||
_ctx: &mut C,
|
{
|
||||||
) -> Result<Self, minicbor::decode::Error> {
|
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||||
d.array()?;
|
d.array()?;
|
||||||
|
|
||||||
match d.u8()? {
|
match d.u8()? {
|
||||||
0 => Ok(Self::Hash(d.decode()?)),
|
0 => Ok(Self::Hash(d.decode_with(ctx)?)),
|
||||||
1 => Ok(Self::Data(d.decode()?)),
|
1 => Ok(Self::Data(d.decode_with(ctx)?)),
|
||||||
_ => Err(minicbor::decode::Error::message(
|
_ => Err(minicbor::decode::Error::message(
|
||||||
"invalid variant for datum option enum",
|
"invalid variant for datum option enum",
|
||||||
)),
|
)),
|
||||||
|
|
@ -481,7 +542,10 @@ impl<'b, C> minicbor::Decode<'b, C> for DatumOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C> minicbor::Encode<C> for DatumOption {
|
impl<C, T> minicbor::Encode<C> for PseudoDatumOption<T>
|
||||||
|
where
|
||||||
|
T: minicbor::Encode<C>,
|
||||||
|
{
|
||||||
fn encode<W: minicbor::encode::Write>(
|
fn encode<W: minicbor::encode::Write>(
|
||||||
&self,
|
&self,
|
||||||
e: &mut minicbor::Encoder<W>,
|
e: &mut minicbor::Encoder<W>,
|
||||||
|
|
@ -496,6 +560,19 @@ impl<C> minicbor::Encode<C> for DatumOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type DatumOption = PseudoDatumOption<PlutusData>;
|
||||||
|
|
||||||
|
pub type MintedDatumOption<'b> = PseudoDatumOption<KeepRaw<'b, PlutusData>>;
|
||||||
|
|
||||||
|
impl<'b> From<MintedDatumOption<'b>> for DatumOption {
|
||||||
|
fn from(value: MintedDatumOption<'b>) -> Self {
|
||||||
|
match value {
|
||||||
|
PseudoDatumOption::Hash(x) => Self::Hash(x),
|
||||||
|
PseudoDatumOption::Data(x) => Self::Data(CborWrap(x.unwrap().unwrap())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// script_ref = #6.24(bytes .cbor script)
|
// script_ref = #6.24(bytes .cbor script)
|
||||||
pub type ScriptRef = CborWrap<Script>;
|
pub type ScriptRef = CborWrap<Script>;
|
||||||
|
|
||||||
|
|
@ -552,63 +629,60 @@ pub use crate::alonzo::AuxiliaryData;
|
||||||
pub use crate::alonzo::TransactionIndex;
|
pub use crate::alonzo::TransactionIndex;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
|
#[derive(Serialize, Deserialize, Encode, Decode, Debug, PartialEq, Clone)]
|
||||||
pub struct Block {
|
pub struct PseudoBlock<T1, T2, T3, T4>
|
||||||
|
where
|
||||||
|
T4: std::clone::Clone,
|
||||||
|
{
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub header: Header,
|
pub header: T1,
|
||||||
|
|
||||||
#[b(1)]
|
#[b(1)]
|
||||||
pub transaction_bodies: Vec<TransactionBody>,
|
pub transaction_bodies: MaybeIndefArray<T2>,
|
||||||
|
|
||||||
#[n(2)]
|
#[n(2)]
|
||||||
pub transaction_witness_sets: Vec<WitnessSet>,
|
pub transaction_witness_sets: MaybeIndefArray<T3>,
|
||||||
|
|
||||||
#[n(3)]
|
#[n(3)]
|
||||||
pub auxiliary_data_set: KeyValuePairs<TransactionIndex, AuxiliaryData>,
|
pub auxiliary_data_set: KeyValuePairs<TransactionIndex, T4>,
|
||||||
|
|
||||||
#[n(4)]
|
#[n(4)]
|
||||||
pub invalid_transactions: Option<Vec<TransactionIndex>>,
|
pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type Block = PseudoBlock<Header, TransactionBody, WitnessSet, AuxiliaryData>;
|
||||||
|
|
||||||
/// A memory representation of an already minted block
|
/// A memory representation of an already minted block
|
||||||
///
|
///
|
||||||
/// This structure is analogous to [Block], but it allows to retrieve the
|
/// This structure is analogous to [Block], but it allows to retrieve the
|
||||||
/// original CBOR bytes for each structure that might require hashing. In this
|
/// original CBOR bytes for each structure that might require hashing. In this
|
||||||
/// way, we make sure that the resulting hash matches what exists on-chain.
|
/// way, we make sure that the resulting hash matches what exists on-chain.
|
||||||
#[derive(Encode, Decode, Debug, PartialEq, Clone)]
|
pub type MintedBlock<'b> = PseudoBlock<
|
||||||
pub struct MintedBlock<'b> {
|
KeepRaw<'b, Header>,
|
||||||
#[n(0)]
|
KeepRaw<'b, MintedTransactionBody<'b>>,
|
||||||
pub header: KeepRaw<'b, Header>,
|
KeepRaw<'b, MintedWitnessSet<'b>>,
|
||||||
|
KeepRaw<'b, AuxiliaryData>,
|
||||||
#[b(1)]
|
>;
|
||||||
pub transaction_bodies: MaybeIndefArray<KeepRaw<'b, TransactionBody>>,
|
|
||||||
|
|
||||||
#[n(2)]
|
|
||||||
pub transaction_witness_sets: MaybeIndefArray<KeepRaw<'b, MintedWitnessSet<'b>>>,
|
|
||||||
|
|
||||||
#[n(3)]
|
|
||||||
pub auxiliary_data_set: KeyValuePairs<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
|
|
||||||
|
|
||||||
#[n(4)]
|
|
||||||
pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'b> From<MintedBlock<'b>> for Block {
|
impl<'b> From<MintedBlock<'b>> for Block {
|
||||||
fn from(x: MintedBlock<'b>) -> Self {
|
fn from(x: MintedBlock<'b>) -> Self {
|
||||||
Block {
|
Block {
|
||||||
header: x.header.unwrap(),
|
header: x.header.unwrap(),
|
||||||
transaction_bodies: x
|
transaction_bodies: MaybeIndefArray::Def(
|
||||||
.transaction_bodies
|
x.transaction_bodies
|
||||||
.to_vec()
|
.iter()
|
||||||
.into_iter()
|
.cloned()
|
||||||
.map(|x| x.unwrap())
|
.map(|x| x.unwrap())
|
||||||
.collect(),
|
.map(TransactionBody::from)
|
||||||
transaction_witness_sets: x
|
.collect(),
|
||||||
.transaction_witness_sets
|
),
|
||||||
.to_vec()
|
transaction_witness_sets: MaybeIndefArray::Def(
|
||||||
.into_iter()
|
x.transaction_witness_sets
|
||||||
.map(|x| x.unwrap())
|
.iter()
|
||||||
.map(WitnessSet::from)
|
.cloned()
|
||||||
.collect(),
|
.map(|x| x.unwrap())
|
||||||
|
.map(WitnessSet::from)
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
auxiliary_data_set: x
|
auxiliary_data_set: x
|
||||||
.auxiliary_data_set
|
.auxiliary_data_set
|
||||||
.to_vec()
|
.to_vec()
|
||||||
|
|
@ -616,45 +690,43 @@ impl<'b> From<MintedBlock<'b>> for Block {
|
||||||
.map(|(k, v)| (k, v.unwrap()))
|
.map(|(k, v)| (k, v.unwrap()))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into(),
|
.into(),
|
||||||
invalid_transactions: x.invalid_transactions.map(|x| x.into()),
|
invalid_transactions: x.invalid_transactions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Encode, Decode, Debug)]
|
#[derive(Clone, Serialize, Deserialize, Encode, Decode, Debug)]
|
||||||
pub struct Tx {
|
pub struct PseudoTx<T1, T2, T3>
|
||||||
|
where
|
||||||
|
T1: std::clone::Clone,
|
||||||
|
T2: std::clone::Clone,
|
||||||
|
T3: std::clone::Clone,
|
||||||
|
{
|
||||||
#[n(0)]
|
#[n(0)]
|
||||||
pub transaction_body: TransactionBody,
|
pub transaction_body: T1,
|
||||||
|
|
||||||
#[n(1)]
|
#[n(1)]
|
||||||
pub transaction_witness_set: WitnessSet,
|
pub transaction_witness_set: T2,
|
||||||
|
|
||||||
#[n(2)]
|
#[n(2)]
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
|
|
||||||
#[n(3)]
|
#[n(3)]
|
||||||
pub auxiliary_data: Nullable<AuxiliaryData>,
|
pub auxiliary_data: Nullable<T3>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug, Clone)]
|
pub type Tx = PseudoTx<TransactionBody, WitnessSet, AuxiliaryData>;
|
||||||
pub struct MintedTx<'b> {
|
|
||||||
#[b(0)]
|
|
||||||
pub transaction_body: KeepRaw<'b, TransactionBody>,
|
|
||||||
|
|
||||||
#[n(1)]
|
pub type MintedTx<'b> = PseudoTx<
|
||||||
pub transaction_witness_set: KeepRaw<'b, MintedWitnessSet<'b>>,
|
KeepRaw<'b, MintedTransactionBody<'b>>,
|
||||||
|
KeepRaw<'b, MintedWitnessSet<'b>>,
|
||||||
#[n(2)]
|
KeepRaw<'b, AuxiliaryData>,
|
||||||
pub success: bool,
|
>;
|
||||||
|
|
||||||
#[n(3)]
|
|
||||||
pub auxiliary_data: Nullable<KeepRaw<'b, AuxiliaryData>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'b> From<MintedTx<'b>> for Tx {
|
impl<'b> From<MintedTx<'b>> for Tx {
|
||||||
fn from(x: MintedTx<'b>) -> Self {
|
fn from(x: MintedTx<'b>) -> Self {
|
||||||
Tx {
|
Tx {
|
||||||
transaction_body: x.transaction_body.unwrap(),
|
transaction_body: x.transaction_body.unwrap().into(),
|
||||||
transaction_witness_set: x.transaction_witness_set.unwrap().into(),
|
transaction_witness_set: x.transaction_witness_set.unwrap().into(),
|
||||||
success: x.success,
|
success: x.success,
|
||||||
auxiliary_data: x.auxiliary_data.map(|x| x.unwrap()),
|
auxiliary_data: x.auxiliary_data.map(|x| x.unwrap()),
|
||||||
|
|
@ -686,6 +758,8 @@ mod tests {
|
||||||
include_str!("../../../test_data/babbage7.block"),
|
include_str!("../../../test_data/babbage7.block"),
|
||||||
// block with indef bytes for plutus data bignum
|
// block with indef bytes for plutus data bignum
|
||||||
include_str!("../../../test_data/babbage8.block"),
|
include_str!("../../../test_data/babbage8.block"),
|
||||||
|
// block with inline datum that fails hashes
|
||||||
|
include_str!("../../../test_data/babbage9.block"),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (idx, block_str) in test_blocks.iter().enumerate() {
|
for (idx, block_str) in test_blocks.iter().enumerate() {
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,11 @@ impl<'b> MultiEraOutput<'b> {
|
||||||
match self {
|
match self {
|
||||||
MultiEraOutput::Byron(x) => x.amount,
|
MultiEraOutput::Byron(x) => x.amount,
|
||||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||||
babbage::TransactionOutput::Legacy(x) => match x.amount {
|
babbage::MintedTransactionOutput::Legacy(x) => match x.amount {
|
||||||
babbage::Value::Coin(c) => c,
|
babbage::Value::Coin(c) => c,
|
||||||
babbage::Value::Multiasset(c, _) => c,
|
babbage::Value::Multiasset(c, _) => c,
|
||||||
},
|
},
|
||||||
babbage::TransactionOutput::PostAlonzo(x) => match x.value {
|
babbage::MintedTransactionOutput::PostAlonzo(x) => match x.value {
|
||||||
babbage::Value::Coin(c) => c,
|
babbage::Value::Coin(c) => c,
|
||||||
babbage::Value::Multiasset(c, _) => c,
|
babbage::Value::Multiasset(c, _) => c,
|
||||||
},
|
},
|
||||||
|
|
@ -80,11 +80,11 @@ impl<'b> MultiEraOutput<'b> {
|
||||||
match self {
|
match self {
|
||||||
MultiEraOutput::Byron(_) => vec![],
|
MultiEraOutput::Byron(_) => vec![],
|
||||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||||
babbage::TransactionOutput::Legacy(x) => match &x.amount {
|
babbage::MintedTransactionOutput::Legacy(x) => match &x.amount {
|
||||||
babbage::Value::Coin(_) => vec![],
|
babbage::Value::Coin(_) => vec![],
|
||||||
babbage::Value::Multiasset(_, x) => collect_multiassets(x),
|
babbage::Value::Multiasset(_, x) => collect_multiassets(x),
|
||||||
},
|
},
|
||||||
babbage::TransactionOutput::PostAlonzo(x) => match &x.value {
|
babbage::MintedTransactionOutput::PostAlonzo(x) => match &x.value {
|
||||||
babbage::Value::Coin(_) => vec![],
|
babbage::Value::Coin(_) => vec![],
|
||||||
babbage::Value::Multiasset(_, x) => collect_multiassets(x),
|
babbage::Value::Multiasset(_, x) => collect_multiassets(x),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,12 @@ impl OriginalHash<32> for KeepRaw<'_, babbage::TransactionBody> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl OriginalHash<32> for KeepRaw<'_, babbage::MintedTransactionBody<'_>> {
|
||||||
|
fn original_hash(&self) -> pallas_crypto::hash::Hash<32> {
|
||||||
|
Hasher::<256>::hash(self.raw_cbor())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ComputeHash<32> for babbage::DatumOption {
|
impl ComputeHash<32> for babbage::DatumOption {
|
||||||
fn compute_hash(&self) -> Hash<32> {
|
fn compute_hash(&self) -> Hash<32> {
|
||||||
match self {
|
match self {
|
||||||
|
|
@ -138,12 +144,13 @@ impl ComputeHash<32> for babbage::DatumOption {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{Era, MultiEraTx};
|
use crate::{Era, MultiEraBlock, MultiEraTx};
|
||||||
|
|
||||||
use super::{ComputeHash, OriginalHash};
|
use super::{ComputeHash, OriginalHash};
|
||||||
use pallas_codec::utils::Int;
|
use pallas_codec::utils::Int;
|
||||||
use pallas_codec::{minicbor, utils::Bytes};
|
use pallas_codec::{minicbor, utils::Bytes};
|
||||||
use pallas_crypto::hash::Hash;
|
use pallas_crypto::hash::Hash;
|
||||||
|
use pallas_primitives::babbage::MintedDatumOption;
|
||||||
use pallas_primitives::{alonzo, babbage, byron};
|
use pallas_primitives::{alonzo, babbage, byron};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
|
@ -328,7 +335,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_datum_hash_respects_original_cbor() {
|
fn test_witness_datum_hash_respects_original_cbor() {
|
||||||
let expected = [
|
let expected = [
|
||||||
"54ad3c112d58e8946480e21d6a35b2a215d1a9a8f540c13714ded86e4b0b6aea",
|
"54ad3c112d58e8946480e21d6a35b2a215d1a9a8f540c13714ded86e4b0b6aea",
|
||||||
"831a557bc2948e1b8c9f5e8e594d62299abff4eb1a11dc19da38bfaf9f2da407",
|
"831a557bc2948e1b8c9f5e8e594d62299abff4eb1a11dc19da38bfaf9f2da407",
|
||||||
|
|
@ -347,4 +354,19 @@ mod tests {
|
||||||
assert_eq!(datum.original_hash().to_string(), expected_hash);
|
assert_eq!(datum.original_hash().to_string(), expected_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_inline_datum_hash_respects_original_cbor() {
|
||||||
|
let expected = "7607117edd3189347a2898defbb9042e9ea3bf094466718cdaf65f7f9bfeefdb";
|
||||||
|
|
||||||
|
let tx_hex = include_str!("../../test_data/babbage2.tx");
|
||||||
|
let tx_bytes = hex::decode(tx_hex).unwrap();
|
||||||
|
let tx = MultiEraTx::decode(Era::Babbage, &tx_bytes).unwrap();
|
||||||
|
|
||||||
|
for output in tx.outputs() {
|
||||||
|
if let Some(MintedDatumOption::Data(datum)) = output.datum() {
|
||||||
|
assert_eq!(datum.original_hash().to_string(), expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ pub enum MultiEraTx<'b> {
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum MultiEraOutput<'b> {
|
pub enum MultiEraOutput<'b> {
|
||||||
AlonzoCompatible(Box<Cow<'b, alonzo::TransactionOutput>>),
|
AlonzoCompatible(Box<Cow<'b, alonzo::TransactionOutput>>),
|
||||||
Babbage(Box<Cow<'b, babbage::TransactionOutput>>),
|
Babbage(Box<Cow<'b, babbage::MintedTransactionOutput<'b>>>),
|
||||||
Byron(Box<Cow<'b, byron::TxOut>>),
|
Byron(Box<Cow<'b, byron::TxOut>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,20 @@ impl<'b> MultiEraOutput<'b> {
|
||||||
Self::AlonzoCompatible(Box::new(Cow::Borrowed(output)))
|
Self::AlonzoCompatible(Box::new(Cow::Borrowed(output)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_babbage(output: &'b babbage::TransactionOutput) -> Self {
|
pub fn from_babbage(output: &'b babbage::MintedTransactionOutput<'b>) -> Self {
|
||||||
Self::Babbage(Box::new(Cow::Borrowed(output)))
|
Self::Babbage(Box::new(Cow::Borrowed(output)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn datum(&self) -> Option<babbage::DatumOption> {
|
pub fn datum(&self) -> Option<babbage::MintedDatumOption> {
|
||||||
match self {
|
match self {
|
||||||
MultiEraOutput::AlonzoCompatible(x) => x.datum_hash.map(babbage::DatumOption::Hash),
|
MultiEraOutput::AlonzoCompatible(x) => {
|
||||||
|
x.datum_hash.map(babbage::MintedDatumOption::Hash)
|
||||||
|
}
|
||||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||||
babbage::TransactionOutput::Legacy(x) => {
|
babbage::MintedTransactionOutput::Legacy(x) => {
|
||||||
x.datum_hash.map(babbage::DatumOption::Hash)
|
x.datum_hash.map(babbage::MintedDatumOption::Hash)
|
||||||
}
|
}
|
||||||
babbage::TransactionOutput::PostAlonzo(x) => x.datum_option.clone(),
|
babbage::MintedTransactionOutput::PostAlonzo(x) => x.datum_option.clone(),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
@ -35,8 +37,8 @@ impl<'b> MultiEraOutput<'b> {
|
||||||
pub fn script_ref(&self) -> Option<&babbage::ScriptRef> {
|
pub fn script_ref(&self) -> Option<&babbage::ScriptRef> {
|
||||||
match &self {
|
match &self {
|
||||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||||
babbage::TransactionOutput::Legacy(_) => None,
|
babbage::MintedTransactionOutput::Legacy(_) => None,
|
||||||
babbage::TransactionOutput::PostAlonzo(x) => x.script_ref.as_ref(),
|
babbage::MintedTransactionOutput::PostAlonzo(x) => x.script_ref.as_ref(),
|
||||||
},
|
},
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
|
@ -46,8 +48,8 @@ impl<'b> MultiEraOutput<'b> {
|
||||||
match self {
|
match self {
|
||||||
MultiEraOutput::AlonzoCompatible(x) => Address::from_bytes(&x.address),
|
MultiEraOutput::AlonzoCompatible(x) => Address::from_bytes(&x.address),
|
||||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||||
babbage::TransactionOutput::Legacy(x) => Address::from_bytes(&x.address),
|
babbage::MintedTransactionOutput::Legacy(x) => Address::from_bytes(&x.address),
|
||||||
babbage::TransactionOutput::PostAlonzo(x) => Address::from_bytes(&x.address),
|
babbage::MintedTransactionOutput::PostAlonzo(x) => Address::from_bytes(&x.address),
|
||||||
},
|
},
|
||||||
MultiEraOutput::Byron(x) => {
|
MultiEraOutput::Byron(x) => {
|
||||||
Ok(ByronAddress::new(&x.address.payload.0, x.address.crc).into())
|
Ok(ByronAddress::new(&x.address.payload.0, x.address.crc).into())
|
||||||
|
|
@ -55,7 +57,7 @@ impl<'b> MultiEraOutput<'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_babbage(&self) -> Option<&babbage::TransactionOutput> {
|
pub fn as_babbage(&self) -> Option<&babbage::MintedTransactionOutput> {
|
||||||
match self {
|
match self {
|
||||||
MultiEraOutput::AlonzoCompatible(_) => None,
|
MultiEraOutput::AlonzoCompatible(_) => None,
|
||||||
MultiEraOutput::Babbage(x) => Some(x),
|
MultiEraOutput::Babbage(x) => Some(x),
|
||||||
|
|
|
||||||
1
test_data/babbage2.tx
Normal file
1
test_data/babbage2.tx
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
84a5008282582096ad42555f60d076d1d86637c248432e31818e288120909548696887715b9b37018258202b4d18700aec5488599d4b864259ac9a7b09ea04cec6042964dd76f9a5832a05030184a300583931ec3422599965ef95b3574c102313371078ec63851fdd7b266cd1bcc05ea481523030b23a495286ca1a18bd141a493e9b5a19d889953f6cdb01821a00286144a1581c0df03e726bb329f8ba9ce709a03b2c033ef5687a337c2ba17d229e9aa150000643b0537472616e6765456767323201028201d818590148d87982a7446e616d654e537472616e67654567672023323245436f6c6f7245426c61636b4566696c657381a3437372635835697066733a2f2f516d623347744a7a365539614a7855776a796d6b4e716932503166316f4251766f783870765a725077694850316f446e616d654e537472616e676545676720233232496d656469615479706549696d6167652f706e6745696d6167655835697066733a2f2f516d623347744a7a365539614a7855776a796d6b4e716932503166316f4251766f783870765a725077694850316f496d656469615479706549696d6167652f706e674a4261636b67726f756e6444426c75654c636f6e747261637444617461d879860181581c3f1d8ef8617f27510a4c213029feced2afaf0b06b25f72785adad603d87980581c0df03e726bb329f8ba9ce709a03b2c033ef5687a337c2ba17d229e9ad87a80d87a800182583901dfcb5f6c42f7529f31be82e0e68a75c2db94e425409770341011ef805ea481523030b23a495286ca1a18bd141a493e9b5a19d889953f6cdb1a000fa3e88258390192e8a9e8538aa4a72fa6d236ab50d4432872ccf4d6fbed11203060a6967aecccd47781661edb1e7c856c7c2e0781b51de468a796809f22b1821a001226b8a1581c0df03e726bb329f8ba9ce709a03b2c033ef5687a337c2ba17d229e9aa150000de140537472616e67654567673232018258390192e8a9e8538aa4a72fa6d236ab50d4432872ccf4d6fbed11203060a6967aecccd47781661edb1e7c856c7c2e0781b51de468a796809f22b1821a008e08beab581c1564a0fe01cdc09a25b5884b1d0bd23a915a2871001523fb80983043a145746573743301581c2d4e5ff9c9217aa6ea71dc7fc34e33eb93882365e7c785c8abd7a46ca2581c5468655661756c744b65657065722d436f6d6963732d3030312d333601581c5468655661756c744b65657065722d436f6d6963732d3030322d373701581c3270d31cb0803a014924e186d1f0b672ccff0ecb9f6d4b4e2709b301a3484669676874353036014846696768743534300148466967687435383701581c3f75c1332868430e28e156f6309836de8df19b620ab604c166741836a4505468654d616e6472696c6c7a3133383101505468654d616e6472696c6c7a3532363201505468654d616e6472696c6c7a3734343201505468654d616e6472696c6c7a3737333101581c4e7d0d6db3ab5a7ffc58b42b2c7c9d21940cd8a8c2650865a51267e2a155466f7274476f7474656e457030314b69643036373301581c544571c086d0e5c5022aca9717dd0f438e21190abb48f37b3ae129f0a14447524f5701581c5ad8deb64bfec21ad2d96e1270b5873d0c4d0f231b928b4c39eb2435a14661646f7369611a047868c0581c604972deb3891e0dc8a6133163053262d89c3f9ba3ed0c34ba5a51e8a44b4f75746c61772023373236014b4f75746c61772023373535014b4f75746c61772023393231014b4f75746c6177202339373701581c641f0571d02b45b868ac1c479fc8118c5be6744ec3d2c5e13bd888b6a1465a4f4d424945191388581c6954264b15bc92d6d592febeac84f14645e1ed46ca5ebb9acdb5c15fa14553545249501988b8581c8654e8b350e298c80d2451beb5ed80fc9eee9f38ce6b039fb8706bc3a1474c4f42535445521a000f4240021a0003955d031a04fdbaa609a1581c0df03e726bb329f8ba9ce709a03b2c033ef5687a337c2ba17d229e9aa250000643b0537472616e676545676732320150000de140537472616e6765456767323201a20082825820e24fabaa6269567e4a129d1b8e84c653ace22addecfef2f0e5e253bab19de8cd584062ee64a666b1d5027df48daf9a34bf15878e4cd4dfbde2fa5ff176e3d642e5dc20d282404fd28a70b3997c6ab6d9520b5116cb5ee1a2b21275a698e82cca2400825820b0342238145d9d7541c720bc49f5dcecd6bd93ec393ca5a68210b0b55a216ec05840b6ee3663bab18f755bac47aface2cdf5690bfced8e176fc547bec5856e670a3a67e9cec2d25c386ed826eaf9d0eb2e2ffda27f369f7609599e45800059f15f0b01818201828200581c3f1d8ef8617f27510a4c213029feced2afaf0b06b25f72785adad60382051a06b4b5c7f5f6
|
||||||
1
test_data/babbage9.block
Normal file
1
test_data/babbage9.block
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue