feat(primitives): Introduce MintedBlock concept (#116)

This commit is contained in:
Santiago Carmuega 2022-06-12 10:44:16 -03:00 committed by GitHub
parent 0a5226dcfd
commit c9489c3ddf
48 changed files with 214 additions and 188 deletions

View file

@ -15,8 +15,11 @@ impl TransactionOutput {
#[cfg(test)]
mod tests {
use crate::alonzo::{BlockWrapper, TransactionBodyComponent};
use crate::Fragment;
use pallas_codec::minicbor;
use crate::alonzo::{Block, TransactionBodyComponent};
type BlockWrapper = (u16, Block);
const KNOWN_ADDRESSES: &[&str] =&[
"addr_test1vzzql63nddp8qdgka578hx6pats290js9kmn4uay5we9fwsgza0z3",
@ -36,10 +39,10 @@ mod tests {
fn known_address_matches() {
// TODO: expand this test to include more test blocks
let block_idx = 1;
let block_str = include_str!("../test_data/alonzo2.block");
let block_str = include_str!("../../../test_data/alonzo2.block");
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
let BlockWrapper(_, block) = BlockWrapper::decode_fragment(&block_bytes[..])
let (_, block): BlockWrapper = minicbor::decode(&block_bytes[..])
.expect(&format!("error decoding cbor for file {}", block_idx));
// don't want to pass if we don't have tx in the block

View file

@ -50,21 +50,24 @@ impl ToHash<32> for KeepRaw<'_, TransactionBody> {
mod tests {
use std::str::FromStr;
use pallas_codec::minicbor;
use pallas_codec::minicbor::data::Int;
use pallas_codec::utils::MaybeIndefArray;
use pallas_crypto::hash::Hash;
use crate::alonzo::{BigInt, BlockWrapper, Constr, NativeScript, PlutusData};
use crate::{Fragment, ToHash};
use crate::alonzo::{BigInt, Constr, MintedBlock, NativeScript, PlutusData};
use crate::ToHash;
type BlockWrapper<'b> = (u16, MintedBlock<'b>);
#[test]
fn transaction_hash_works() {
// TODO: expand this test to include more test blocks
let block_idx = 1;
let block_str = include_str!("../test_data/alonzo1.block");
let block_str = include_str!("../../../test_data/alonzo1.block");
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
let block_model = BlockWrapper::decode_fragment(&block_bytes[..])
let (_, block_model): BlockWrapper = minicbor::decode(&block_bytes[..])
.expect(&format!("error decoding cbor for file {}", block_idx));
let valid_hashes = vec![
@ -75,7 +78,7 @@ mod tests {
"8838f5ab27894a6543255aeaec086f7b3405a6db6e7457a541409cdbbf0cd474",
];
for (tx_idx, tx) in block_model.1.transaction_bodies.iter().enumerate() {
for (tx_idx, tx) in block_model.transaction_bodies.iter().enumerate() {
let computed_hash = tx.to_hash();
let known_hash = valid_hashes[tx_idx];
assert_eq!(hex::encode(computed_hash), known_hash)

View file

@ -80,13 +80,17 @@ impl ToCanonicalJson for super::NativeScript {
#[cfg(test)]
mod tests {
use crate::{alonzo::BlockWrapper, Fragment, ToCanonicalJson};
use pallas_codec::minicbor;
use crate::{alonzo::Block, ToCanonicalJson};
type BlockWrapper = (u16, Block);
#[test]
fn test_datums_serialize_as_expected() {
let test_blocks = vec![(
include_str!("../test_data/alonzo9.block"),
include_str!("../test_data/alonzo9.datums"),
include_str!("../../../test_data/alonzo9.block"),
include_str!("../../../test_data/alonzo9.datums"),
)];
for (idx, (block_str, jsonl_str)) in test_blocks.iter().enumerate() {
@ -94,7 +98,7 @@ mod tests {
let bytes = hex::decode(block_str).expect(&format!("bad block file {}", idx));
let BlockWrapper(_, block) = BlockWrapper::decode_fragment(&bytes[..])
let (_, block): BlockWrapper = minicbor::decode(&bytes[..])
.expect(&format!("error decoding cbor for file {}", idx));
let mut datums = jsonl_str.lines();
@ -115,8 +119,8 @@ mod tests {
#[test]
fn test_native_scripts_serialize_as_expected() {
let test_blocks = vec![(
include_str!("../test_data/alonzo9.block"),
include_str!("../test_data/alonzo9.native"),
include_str!("../../../test_data/alonzo9.block"),
include_str!("../../../test_data/alonzo9.native"),
)];
for (idx, (block_str, jsonl_str)) in test_blocks.iter().enumerate() {
@ -124,7 +128,7 @@ mod tests {
let bytes = hex::decode(block_str).expect(&format!("bad block file {}", idx));
let BlockWrapper(_, block) = BlockWrapper::decode_fragment(&bytes[..])
let (_, block): BlockWrapper = minicbor::decode(&bytes[..])
.expect(&format!("error decoding cbor for file {}", idx));
let mut scripts = jsonl_str.lines();

View file

@ -1418,12 +1418,12 @@ impl<C> minicbor::Encode<C> for AuxiliaryData {
pub type TransactionIndex = u32;
#[derive(Encode, Decode, Debug, PartialEq)]
pub struct Block<'b> {
pub struct Block {
#[n(0)]
pub header: Header,
#[b(1)]
pub transaction_bodies: MaybeIndefArray<KeepRaw<'b, TransactionBody>>,
pub transaction_bodies: MaybeIndefArray<TransactionBody>,
#[n(2)]
pub transaction_witness_sets: MaybeIndefArray<TransactionWitnessSet>,
@ -1435,82 +1435,107 @@ pub struct Block<'b> {
pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
}
#[derive(Encode, Decode, Debug)]
pub struct BlockWrapper<'b>(#[n(0)] pub u16, #[b(1)] pub Block<'b>);
/// A memory representation of an already minted block
///
/// This structure is analogous to [Block], but it allows to retrieve the
/// 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.
#[derive(Encode, Decode, Debug, PartialEq)]
pub struct MintedBlock<'b> {
#[n(0)]
pub header: KeepRaw<'b, Header>,
#[b(1)]
pub transaction_bodies: MaybeIndefArray<KeepRaw<'b, TransactionBody>>,
#[n(2)]
pub transaction_witness_sets: MaybeIndefArray<TransactionWitnessSet>,
#[n(3)]
pub auxiliary_data_set: KeyValuePairs<TransactionIndex, KeepRaw<'b, AuxiliaryData>>,
#[n(4)]
pub invalid_transactions: Option<MaybeIndefArray<TransactionIndex>>,
}
#[derive(Encode, Decode, Debug)]
pub struct Transaction {
#[n(0)]
transaction_body: TransactionBody,
#[n(1)]
transaction_witness_set: TransactionWitnessSet,
#[n(2)]
success: bool,
#[n(3)]
auxiliary_data: Option<AuxiliaryData>,
}
#[cfg(test)]
mod tests {
use super::BlockWrapper;
use crate::Fragment;
use pallas_codec::minicbor::to_vec;
use pallas_codec::minicbor::{self, to_vec};
use super::MintedBlock;
type BlockWrapper<'b> = (u16, MintedBlock<'b>);
#[test]
fn block_isomorphic_decoding_encoding() {
let test_blocks = vec![
include_str!("../test_data/alonzo1.block"),
include_str!("../test_data/alonzo2.block"),
include_str!("../test_data/alonzo3.block"),
include_str!("../test_data/alonzo4.block"),
include_str!("../test_data/alonzo5.block"),
include_str!("../test_data/alonzo6.block"),
include_str!("../test_data/alonzo7.block"),
include_str!("../test_data/alonzo8.block"),
include_str!("../test_data/alonzo9.block"),
include_str!("../../../test_data/alonzo1.block"),
include_str!("../../../test_data/alonzo2.block"),
include_str!("../../../test_data/alonzo3.block"),
include_str!("../../../test_data/alonzo4.block"),
include_str!("../../../test_data/alonzo5.block"),
include_str!("../../../test_data/alonzo6.block"),
include_str!("../../../test_data/alonzo7.block"),
include_str!("../../../test_data/alonzo8.block"),
include_str!("../../../test_data/alonzo9.block"),
// old block without invalid_transactions fields
include_str!("../test_data/alonzo10.block"),
include_str!("../../../test_data/alonzo10.block"),
// peculiar block with protocol update params
include_str!("../test_data/alonzo11.block"),
include_str!("../../../test_data/alonzo11.block"),
// peculiar block with decoding issue
// https://github.com/txpipe/oura/issues/37
include_str!("../test_data/alonzo12.block"),
include_str!("../../../test_data/alonzo12.block"),
// peculiar block with protocol update params, including nonce
include_str!("../test_data/alonzo13.block"),
include_str!("../../../test_data/alonzo13.block"),
// peculiar block with overflow crash
// https://github.com/txpipe/oura/issues/113
include_str!("../test_data/alonzo14.block"),
include_str!("../../../test_data/alonzo14.block"),
// peculiar block with many move-instantaneous-rewards certs
include_str!("../test_data/alonzo15.block"),
include_str!("../../../test_data/alonzo15.block"),
// peculiar block with protocol update values
include_str!("../test_data/alonzo16.block"),
include_str!("../../../test_data/alonzo16.block"),
// peculiar block with missing nonce hash
include_str!("../test_data/alonzo17.block"),
include_str!("../../../test_data/alonzo17.block"),
// peculiar block with strange AuxiliaryData variant
include_str!("../test_data/alonzo18.block"),
include_str!("../../../test_data/alonzo18.block"),
// peculiar block with strange AuxiliaryData variant
include_str!("../test_data/alonzo18.block"),
include_str!("../../../test_data/alonzo18.block"),
// peculiar block with nevative i64 overflow
include_str!("../test_data/alonzo19.block"),
include_str!("../../../test_data/alonzo19.block"),
// peculiar block with very BigInt in plutus code
include_str!("../test_data/alonzo20.block"),
include_str!("../../../test_data/alonzo20.block"),
// peculiar block with bad tx hash
include_str!("../test_data/alonzo21.block"),
include_str!("../../../test_data/alonzo21.block"),
// peculiar block with bad tx hash
include_str!("../test_data/alonzo22.block"),
include_str!("../../../test_data/alonzo22.block"),
];
for (idx, block_str) in test_blocks.iter().enumerate() {
println!("decoding test block {}", idx + 1);
let bytes = hex::decode(block_str).expect(&format!("bad block file {}", idx));
let block = BlockWrapper::decode_fragment(&bytes[..])
let block: BlockWrapper = minicbor::decode(&bytes[..])
.expect(&format!("error decoding cbor for file {}", idx));
let bytes2 =
to_vec(block).expect(&format!("error encoding block cbor for file {}", idx));
assert_eq!(bytes, bytes2);
assert!(bytes.eq(&bytes2), "re-encoded bytes didn't match original");
}
}
}

View file

@ -13,9 +13,9 @@ impl Address {
#[cfg(test)]
mod tests {
use crate::byron::Block;
use crate::Fragment;
use std::ops::Deref;
use crate::byron::MintedMainBlock;
type BlockWrapper<'b> = (u16, MintedMainBlock<'b>);
const KNOWN_ADDRESSES: &[&str] = &[
"DdzFFzCqrht8QHTQXbWy2qoyPaqTN8BjyfKygGmpy9dtot1tvkBfCaVTnR22XCaaDVn3M1U6aiMShoCLzw6VWSwzQKhhJrM3YjYp3wyy",
@ -32,22 +32,17 @@ mod tests {
fn known_address_matches() {
// TODO: expand this test to include more test blocks
let block_idx = 1;
let block_str = include_str!("test_data/test2.block");
let block_str = include_str!("../../../test_data/byron2.block");
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
let block = Block::decode_fragment(&block_bytes[..])
let (_, block): BlockWrapper = pallas_codec::minicbor::decode(&block_bytes[..])
.expect(&format!("error decoding cbor for file {}", block_idx));
let block = match block {
Block::MainBlock(x) => x,
Block::EbBlock(_) => panic!(),
};
// don't want to pass if we don't have tx in the block
assert!(block.body.tx_payload.len() > 0);
for tx in block.body.tx_payload.iter() {
for output in tx.deref().transaction.outputs.iter() {
for output in tx.transaction.outputs.iter() {
let addr_str = output.address.to_addr_string().unwrap();
assert!(

View file

@ -1,39 +1,56 @@
use super::{Block, BlockHead, EbbHead, Tx};
use crate::ToHash;
use super::{BlockHead, EbbHead, Tx};
use pallas_codec::utils::KeepRaw;
use pallas_crypto::hash::{Hash, Hasher};
impl EbbHead {
pub fn to_hash(&self) -> Hash<32> {
impl ToHash<32> for EbbHead {
fn to_hash(&self) -> Hash<32> {
// hash expects to have a prefix for the type of block
Hasher::<256>::hash_cbor(&(0, self))
}
}
impl BlockHead {
pub fn to_hash(&self) -> Hash<32> {
impl ToHash<32> for KeepRaw<'_, EbbHead> {
fn to_hash(&self) -> Hash<32> {
// hash expects to have a prefix for the type of block
Hasher::<256>::hash_cbor(&(0, self))
}
}
impl ToHash<32> for BlockHead {
fn to_hash(&self) -> Hash<32> {
// hash expects to have a prefix for the type of block
Hasher::<256>::hash_cbor(&(1, self))
}
}
impl Block {
pub fn to_hash(&self) -> Hash<32> {
match self {
Block::EbBlock(x) => x.header.to_hash(),
Block::MainBlock(x) => x.header.to_hash(),
}
impl ToHash<32> for KeepRaw<'_, BlockHead> {
fn to_hash(&self) -> Hash<32> {
// hash expects to have a prefix for the type of block
Hasher::<256>::hash_cbor(&(1, self))
}
}
impl Tx {
pub fn to_hash(&self) -> Hash<32> {
impl ToHash<32> for Tx {
fn to_hash(&self) -> Hash<32> {
Hasher::<256>::hash_cbor(self)
}
}
impl ToHash<32> for KeepRaw<'_, Tx> {
fn to_hash(&self) -> Hash<32> {
Hasher::<256>::hash(self.raw_cbor())
}
}
#[cfg(test)]
mod tests {
use crate::byron::Block;
use crate::Fragment;
use pallas_codec::minicbor;
use crate::{byron::MintedMainBlock, ToHash};
type BlockWrapper<'b> = (u16, MintedMainBlock<'b>);
const KNOWN_HASH: &'static str =
"5c196e7394ace0449ba5a51c919369699b13896e97432894b4f0354dce8670b6";
@ -42,13 +59,13 @@ mod tests {
fn transaction_hash_works() {
// TODO: expand this test to include more test blocks
let block_idx = 1;
let block_str = include_str!("test_data/test1.block");
let block_str = include_str!("../../../test_data/byron1.block");
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
let block_model = Block::decode_fragment(&block_bytes[..])
let (_, block_model): BlockWrapper = minicbor::decode(&block_bytes[..])
.expect(&format!("error decoding cbor for file {}", block_idx));
let computed_hash = block_model.to_hash();
let computed_hash = block_model.header.to_hash();
assert_eq!(hex::encode(computed_hash), KNOWN_HASH)
}

View file

@ -46,24 +46,22 @@ impl TxPayload {
#[cfg(test)]
mod tests {
use crate::byron::Block;
use crate::Fragment;
use pallas_codec::minicbor;
use crate::{byron::MainBlock, ToHash};
type BlockWrapper = (u16, MainBlock);
#[test]
fn known_fee_matches() {
// TODO: expand this test to include more test blocks
let block_idx = 1;
let block_str = include_str!("test_data/test4.block");
let block_str = include_str!("../../../test_data/byron4.block");
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
let block = Block::decode_fragment(&block_bytes[..])
let (_, block): BlockWrapper = minicbor::decode(&block_bytes[..])
.expect(&format!("error decoding cbor for file {}", block_idx));
let block = match block {
Block::MainBlock(x) => x,
Block::EbBlock(_) => panic!(),
};
// don't want to pass if we don't have tx in the block
assert!(block.body.tx_payload.len() > 0);

View file

@ -6,8 +6,8 @@ use pallas_codec::minicbor::{bytes::ByteVec, Decode, Encode};
use pallas_crypto::hash::Hash;
use pallas_codec::utils::{
CborWrap, EmptyMap, KeyValuePairs, MaybeIndefArray, OrderPreservingProperties, TagWrap,
ZeroOrOneArray,
CborWrap, EmptyMap, KeepRaw, KeyValuePairs, MaybeIndefArray, OrderPreservingProperties,
TagWrap, ZeroOrOneArray,
};
// required for derive attrs to work
@ -907,6 +907,18 @@ pub struct MainBlock {
pub extra: MaybeIndefArray<Attributes>,
}
#[derive(Encode, Decode, Debug)]
pub struct MintedMainBlock<'b> {
#[b(0)]
pub header: KeepRaw<'b, BlockHead>,
#[n(1)]
pub body: BlockBody,
#[n(2)]
pub extra: MaybeIndefArray<Attributes>,
}
#[derive(Encode, Decode, Debug)]
pub struct EbBlock {
#[n(0)]
@ -919,79 +931,51 @@ pub struct EbBlock {
pub extra: MaybeIndefArray<Attributes>,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub enum Block {
MainBlock(MainBlock),
EbBlock(EbBlock),
}
impl<'b, C> minicbor::Decode<'b, C> for Block {
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
d.array()?;
let variant = d.u32()?;
match variant {
0 => Ok(Block::EbBlock(d.decode_with(ctx)?)),
1 => Ok(Block::MainBlock(d.decode_with(ctx)?)),
_ => Err(minicbor::decode::Error::message(
"unknown variant for block",
)),
}
}
}
impl minicbor::Encode<()> for Block {
fn encode<W: minicbor::encode::Write>(
&self,
e: &mut minicbor::Encoder<W>,
_ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
match self {
Block::EbBlock(x) => {
e.array(2)?;
e.encode(0)?;
e.encode(x)?;
Ok(())
}
Block::MainBlock(x) => {
e.array(2)?;
e.encode(1)?;
e.encode(x)?;
Ok(())
}
}
}
}
#[cfg(test)]
mod tests {
use crate::byron::{Block, BlockHead};
use crate::Fragment;
use pallas_codec::minicbor::to_vec;
use super::{BlockHead, EbBlock, MintedMainBlock};
use pallas_codec::minicbor::{self, to_vec};
#[test]
fn block_isomorphic_decoding_encoding() {
fn boundary_block_isomorphic_decoding_encoding() {
type BlockWrapper = (u16, EbBlock);
let test_blocks = vec![include_str!("../../../test_data/genesis.block")];
for (idx, block_str) in test_blocks.iter().enumerate() {
println!("decoding test block {}", idx + 1);
let bytes = hex::decode(block_str).expect(&format!("bad block file {}", idx));
let block: BlockWrapper = minicbor::decode(&bytes[..])
.expect(&format!("error decoding cbor for file {}", idx));
let bytes2 =
to_vec(block).expect(&format!("error encoding block cbor for file {}", idx));
assert_eq!(hex::encode(bytes), hex::encode(bytes2));
}
}
#[test]
fn main_block_isomorphic_decoding_encoding() {
type BlockWrapper<'b> = (u16, MintedMainBlock<'b>);
let test_blocks = vec![
include_str!("test_data/genesis.block"),
include_str!("test_data/test1.block"),
include_str!("test_data/test2.block"),
include_str!("test_data/test3.block"),
include_str!("test_data/test4.block"),
include_str!("test_data/test5.block"),
include_str!("test_data/test6.block"),
include_str!("test_data/test7.block"),
//include_str!("../../../test_data/genesis.block"),
include_str!("../../../test_data/byron1.block"),
include_str!("../../../test_data/byron2.block"),
include_str!("../../../test_data/byron3.block"),
include_str!("../../../test_data/byron4.block"),
include_str!("../../../test_data/byron5.block"),
include_str!("../../../test_data/byron6.block"),
include_str!("../../../test_data/byron7.block"),
];
for (idx, block_str) in test_blocks.iter().enumerate() {
println!("decoding test block {}", idx + 1);
let bytes = hex::decode(block_str).expect(&format!("bad block file {}", idx));
let block = Block::decode_fragment(&bytes[..])
let block: BlockWrapper = minicbor::decode(&bytes[..])
.expect(&format!("error decoding cbor for file {}", idx));
let bytes2 =
@ -1003,13 +987,13 @@ mod tests {
#[test]
fn header_isomorphic_decoding_encoding() {
let subjects = vec![include_str!("test_data/test1.header")];
let subjects = vec![include_str!("../../../test_data/byron1.header")];
for (idx, str) in subjects.iter().enumerate() {
println!("decoding test header {}", idx + 1);
let bytes = hex::decode(str).expect(&format!("bad header file {}", idx));
let block = BlockHead::decode_fragment(&bytes[..])
let block: BlockHead = minicbor::decode(&bytes[..])
.expect(&format!("error decoding cbor for file {}", idx));
let bytes2 =

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820183851a2d964a095820a5a5c235200bbe91f16cd3e5dcb67369c25dcfb1279c83d22021f5d960c485e684830058200e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a85820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b82035820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58204e66280cd94d591072349bec0a3090a53aa945562efb6d08d56e53654b0e4098848218cf19545a584026566e86fc6b9b177c8480e275b2b112b573f6d073f9deea53b8d99c4ed976b335b2b3842f0e380001f090bc923caa9691ed9115e286da9421e2745c7acc87f1811a004485098202828400584026566e86fc6b9b177c8480e275b2b112b573f6d073f9deea53b8d99c4ed976b335b2b3842f0e380001f090bc923caa9691ed9115e286da9421e2745c7acc87f15840f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc85dae922d5eb3838d2b91784f04824d26767bfb65bd36a36e74fec46d09d98858d58408ab43e904b06e799c1817c5ced4f3a7bbe15cdbf422dea9d2d5dc2c6105ce2f4d4c71e5d4779f6c44b770a133636109949e1f7786acb5a732bcdea0470fea4065840c15d273e3e0735777e2b38359224803aa4a0fcd1cde37ed1f2f399d7e095b18bdc698a2aff59b2118cbbe45498c7bdc6ccf3a88a806cbd3e73bcf2fc6d7364028483020000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849fff8203d90102809fff82809fff81a0

View file

@ -1 +0,0 @@
851A2D964A0958205C196E7394ACE0449BA5A51C919369699B13896E97432894B4F0354DCE8670B68483015820D09F2306C1CD4756C1A7FF3ADB5DC8D7CADEDF882DBCC06E098C381078449A495820080A7075FDD79C20F6DA7AEEAA8A9765A0F83175851F3BB1AF583BD99F84358B82035820D36A2619A672494604E11BB447CBCF5231E9F2BA25C2169177EDC941BD50AD6C5820AFC0DA64183BF2664F3D4EEC7238D524BA607FAEEAB24FC100EB861DBA69971B58204E66280CD94D591072349BEC0A3090A53AA945562EFB6D08D56E53654B0E4098848218CF19545B58401BC97A2FE02C297880CE8ECFD997FE4C1EC09EE10FEEEE9F686760166B05281D6283468FFD93BECB0C956CCDDD642DF9B1244C915911185FA49355F6F22BFAB9811A0044850A820282840058401BC97A2FE02C297880CE8ECFD997FE4C1EC09EE10FEEEE9F686760166B05281D6283468FFD93BECB0C956CCDDD642DF9B1244C915911185FA49355F6F22BFAB9584061261A95B7613EE6BF2067DAD77B70349729B0C50D57BC1CF30DE0DB4A1E73A885D0054AF7C23FC6C37919DBA41C602A57E2D0F9329A7954B867338D6FB2C9455840E03E62F083DF5576360E60A32E22BBB07B3C8DF4FCAB8079F1D6F61AF3954D242BA8A06516C395939F24096F3DF14E103A7D9C2B80A68A9363CF1F27C7A4E30758409F9CBAA9AE2751FC9D97E7DAE0CEF3E2C6D740627818B735E39EADF92F83A04DC36D42C42D258450F13C0BA3E1470EDE42A1F0D239A99EA284BCAA031A514A098483020000826A63617264616E6F2D736C01A058204BA92AA320C60ACC9AD7B9A64F2EDA55C4D2EC28E604FAF186708B4F0C4E8EDF

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820183851a2d964a095820b5bdd15fbfbe7f618d2b7db0b20632658466b1b17654e9a8b865ec0e9fdccd4e8483015820c2c44f1f28599c08c6c1da0e375dc995d2b686c445b19110fa96ca68dfb2880e5820314b3c77650d6eba459864966dbcda18c438ee21bdd7e6b3272bf1e6b241d75d83025820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58204e66280cd94d591072349bec0a3090a53aa945562efb6d08d56e53654b0e4098848201195457584026566e86fc6b9b177c8480e275b2b112b573f6d073f9deea53b8d99c4ed976b335b2b3842f0e380001f090bc923caa9691ed9115e286da9421e2745c7acc87f18119a89f8202828400584026566e86fc6b9b177c8480e275b2b112b573f6d073f9deea53b8d99c4ed976b335b2b3842f0e380001f090bc923caa9691ed9115e286da9421e2745c7acc87f15840f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc85dae922d5eb3838d2b91784f04824d26767bfb65bd36a36e74fec46d09d98858d58408ab43e904b06e799c1817c5ced4f3a7bbe15cdbf422dea9d2d5dc2c6105ce2f4d4c71e5d4779f6c44b770a133636109949e1f7786acb5a732bcdea0470fea4065840cfd641e91f908471af31762e7124147e8d3b27036d436f24d785de7330ebe33c03dae5ec27eb2944a82545fbcc30016737ba7696fb5e3fcaf8963ea12dbb87098483000000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849f82839f8200d81858248258200ca95f3bb516e3fa36b3c5ce18316a3d197b4faf2e36635baecae47e8a714b8d00ff9f8282d818584283581caca526063940ef762c899b92f20134264a43c5ab36d46cc6d36540d1a101581e581c2729cbfd641133bd0633ff422b246fa0d95cc2bef293d39adf3fd22b001aa25f5bd41b0000021a9f3ab0c28282d818584283581ce0751a974c40abdac7e71ee5b09d12b0591b1f4ecab73062ac8f96caa101581e581cca3e553c9c63c531002ff143535ea35088673bf86d25026baf12db3e001afdf29bac1a02625a00ffa0818200d81858858258408b9397dce473d3f296ad24e24e48795a495ad2f1602896e913fdc7e55e55e21f6fa53491a197e86428c86fadc0253ddec8d88bee623d474632603633643b26eb5840555e2f86fd803d1ed5bb3a3bc7f08dd82896744c4a0d99ce7b61f696ef632b12f6d8bd4787fcfe27de2bb7b1127fb1646d8d2f26755b4186f605210709016709ff8302a0d90102809fff82809fff81a0

View file

@ -1 +0,0 @@
820183851a2d964a0958201d1c6f61db4509a5978d54bd4dd1bad192c4b56086c9b6e419c9b1efa21419138483015820b44c5c051cf7546c6a9a7fc98cb51edc24e46869ddb49daabd01e6afff3cfec5582050689a01eff76204cf488438b0dd871947c2cbc34e858516ecb5e22193609e6283015820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58202475b9c6d41c4f82c2d9c602fa037dc7f4140606067ddf222917acc020ddc0be8482031921ee58401bc97a2fe02c297880ce8ecfd997fe4c1ec09ee10feeee9f686760166b05281d6283468ffd93becb0c956ccddd642df9b1244c915911185fa49355f6f22bfab9811a00011ef2820282840058401bc97a2fe02c297880ce8ecfd997fe4c1ec09ee10feeee9f686760166b05281d6283468ffd93becb0c956ccddd642df9b1244c915911185fa49355f6f22bfab9584061261a95b7613ee6bf2067dad77b70349729b0c50d57bc1cf30de0db4a1e73a885d0054af7c23fc6c37919dba41c602a57e2d0f9329a7954b867338d6fb2c9455840e03e62f083df5576360e60a32e22bbb07b3c8df4fcab8079f1d6f61af3954d242ba8a06516c395939f24096f3df14e103a7d9c2b80a68a9363cf1f27c7a4e3075840b5c04dbfca8d6e5dcf873569105a6f93040a927c33984221dbb54a82f2523b8cfe579a67f5e1f8200d0d888315c5c65969ea32c967aa20a33d447ff1c67da3008483000000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849f82839f8200d8185824825820e6e6c92426711a3ad8c254bf116c68a2c71de5fb5c61a0add8bc5c57497e05bc00ff9f8282d818584283581c656cb181ad933fa9e497d6e67eabdfb2bbd63f230676ddebbe41acdda101581e581cac02fdd1d62f3ad946d729fa2839419f1192554f4b48913c6a26889b001ac279d5cb1b000000199be4bedf8282d818584283581c293da0dcde147aa40929309c7ee99afcf3ddbc9880008708a3189f63a101581e581cca3e553c9c63c5090ff02243e47896711682220940aa695e754b0f47001a8d1241f01a00989680ffa0818200d818588582584082503efed69e7f816a6ea1cc6e9b7d2c909f9427f7ad68764d946041eb735ac487b2168c3c31dbcb1f8c713484d95b41b80a5458c5bce8d2b6d12000d8287cc0584084b8f026ec86a56b02cd88a0ba40c770e5807b71e3c8ccc9a98465816aa2fd24e2f6efd3a1bc5837b2a82f572c779848313f87be10beccba9698d335b919a802ff8301a0d90102809fff828187830000008e810081194e20811a001e8480811a001e848081191000811902bc811b000012309ce54000811b00000045d964b800811b000000e8d4a51000811b00005af3107a400081192710808080826c63736c2d64616564616c757301a2676d61636f73363484582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145820966d92b90edc99f3e946fe16490d0313c56c5c9b570c453c6d1e5cc08cdb6184582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113146577696e363484582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145820828339268d84c542d3543a878ccba21887fbf01fb154d333b945217dedba9c3a582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314a05840e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d190dcc246f56c8e33ac0037066e2f664ddaa985ea5284082643308dde4f5bfedf58405e59935bcabe470872bf305dec2e15a3442d3cf5bc2e3c02d8e1d680e31530ead6ad5ba788f2c185ff0162cb46cddc7360a32c3ba88e5fae63a8c36b8b46450f9f845840e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d190dcc246f56c8e33ac0037066e2f664ddaa985ea5284082643308dde4f5bfedf58200d7d3b53a0ef9ce40fa9222cfc2b725f52c0136c01ad366115b48f94d8ef2c6df55840d723f2794e5206c38b9ed6433190cd75e89ab1e3d9324c89fe0925b924c81b2fadbf83f3e232f583efcb1eae345e3149073e2d85c0eb85324874f13118ce340dff81a0

View file

@ -1 +0,0 @@
820183851a2d964a09582093e8d67112ed5409b0a161bc55f4ddb79b72bdf02734c89a5041141a059cdfdb8483015820a086d48da9573005c66b402ca14945e489774d2515c0292a4342ad7a26045fdd5820d841892fab25e11952d67c8e0b41d01b8fd24ba954aab6c068667f381082862d83025820b52b4cd8e1e399b2131c87eb30300a2ac123623ae73586069c63c57891b26a3c5820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58204e66280cd94d591072349bec0a3090a53aa945562efb6d08d56e53654b0e4098848218a01943805840d2965c869901231798c5d02d39fca2a79aa47c3e854921b5855c82fd1470891517e1fa771655ec8cad13ecf6e5719adc5392fc057e1703d5f583311e837462f1811a0034f77782028284005840d2965c869901231798c5d02d39fca2a79aa47c3e854921b5855c82fd1470891517e1fa771655ec8cad13ecf6e5719adc5392fc057e1703d5f583311e837462f158409180d818e69cd997e34663c418a648c076f2e19cd4194e486e159d8580bc6cda81344440c6ad0e5306fd035bef9281da5d8fbd38f59f588f7081016ee61113d25840cf6ddc111545f61c2442b68bd7864ea952c428d145438948ef48a4af7e3f49b175564007685be5ae3c9ece0ab27de09721db0cb63aa67dc081a9f82d7e84210d58401e30c671d712d5e91e8d5a9cb645548f73e6c368c7bb9c7ea8a1930ae2e256eb4365e2f12ca11e3f3c97f96275a0b45a42c614053cc153abbeab545629d0ed0e8483000200826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849f82839f8200d81858248258203e80dc9866d54a0075a536342bb41cb3ee8bff26e22e79d8b5b02f9058973a5a02ff9f8282d818584283581c46649d0d45e975d78e6c72508c4ef0894a099475e62634ae7551cb46a101581e581c3948cca16608ca0dc589c7f70b120c0369ac7a8dd7aeb87c4e9a08d9001a71b2c97d1a421720a4ffa0818200d81858858258404f502763c5154373653a027d2fcea2590751fcd4e321cc6e50086fa4fbc8945ce7d36e93d9c615e15be2a6321633851ddcd8e3f3f7aa41dfc1443a30fedd063958408e02e75df5172c5c8a9db04f6432a4ad27013f2563af7b4c097153b831fc212aec72f1a240bed1823f09017684912526d215cd2fbd52b84800017182ed573d08ff8302a1581c0efd6f3b2849d5baf25b3e2bf2d46f88427b4e455fc3dc43f57819c5a1581c0efd6f3b2849d5baf25b3e2bf2d46f88427b4e455fc3dc43f57819c59f58635861024e8340fd6c8b5eaed7ee19f79bbd2626f24b6edc4255d3fe58cc3e342de0b429e42bdcfaeb3917455874accb0a342e1683bf3c598c6bb7958436ae1440dd889f3fcc17c53bd1ffa6f32100e250ef00e6e11be44deb1a36b7c6ecd83ad04d6bdeffd90102809fff82809fff81a0

File diff suppressed because one or more lines are too long

View file

@ -22,24 +22,22 @@ impl EbbHead {
#[cfg(test)]
mod tests {
use crate::byron::Block;
use crate::Fragment;
use pallas_codec::minicbor;
use crate::byron::MainBlock;
type BlockWrapper = (u16, MainBlock);
#[test]
fn knwon_slot_matches() {
// TODO: expand this test to include more test blocks
let block_idx = 1;
let block_str = include_str!("test_data/test1.block");
let block_str = include_str!("../../../test_data/byron1.block");
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
let block = Block::decode_fragment(&block_bytes[..])
let (_, block): BlockWrapper = minicbor::decode(&block_bytes[..])
.expect(&format!("error decoding cbor for file {}", block_idx));
let block = match block {
Block::MainBlock(x) => x,
Block::EbBlock(_) => panic!(),
};
let computed_slot = block.header.consensus_data.0.to_abs_slot();
assert_eq!(computed_slot, 4492794);

View file

@ -23,11 +23,6 @@ where
}
}
#[cfg(feature = "json")]
pub trait ToCanonicalJson {
fn to_json(&self) -> serde_json::Value;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Era {
Byron,
@ -37,6 +32,11 @@ pub enum Era {
Alonzo, // smart-contracts
}
#[cfg(feature = "json")]
pub trait ToCanonicalJson {
fn to_json(&self) -> serde_json::Value;
}
pub trait ToHash<const BYTES: usize> {
fn to_hash(&self) -> pallas_crypto::hash::Hash<BYTES>;
}

View file

@ -7,7 +7,7 @@ use crate::Era;
#[derive(Debug)]
pub enum Outcome {
Matched(Era),
GenesisBlock,
EpochBoundary,
Inconclusive,
}
@ -23,7 +23,7 @@ pub fn probe_block_cbor_era(cbor: &[u8]) -> Outcome {
match tokenizer.next() {
Some(Ok(Token::U8(variant))) => match variant {
0 => Outcome::GenesisBlock,
0 => Outcome::EpochBoundary,
1 => Outcome::Matched(Era::Byron),
2 => Outcome::Matched(Era::Shelley),
3 => Outcome::Matched(Era::Allegra),
@ -41,17 +41,17 @@ mod tests {
#[test]
fn genesis_block_detected() {
let block_str = include_str!("byron/test_data/genesis.block");
let block_str = include_str!("../../test_data/genesis.block");
let bytes = hex::decode(block_str).unwrap();
let inference = probe_block_cbor_era(bytes.as_slice());
assert!(matches!(inference, Outcome::GenesisBlock));
assert!(matches!(inference, Outcome::EpochBoundary));
}
#[test]
fn byron_block_detected() {
let block_str = include_str!("byron/test_data/test1.block");
let block_str = include_str!("../../test_data/byron1.block");
let bytes = hex::decode(block_str).unwrap();
let inference = probe_block_cbor_era(bytes.as_slice());
@ -61,7 +61,7 @@ mod tests {
#[test]
fn shelley_block_detected() {
let block_str = include_str!("test_data/shelley1.block");
let block_str = include_str!("../../test_data/shelley1.block");
let bytes = hex::decode(block_str).unwrap();
let inference = probe_block_cbor_era(bytes.as_slice());
@ -71,7 +71,7 @@ mod tests {
#[test]
fn allegra_block_detected() {
let block_str = include_str!("test_data/allegra1.block");
let block_str = include_str!("../../test_data/allegra1.block");
let bytes = hex::decode(block_str).unwrap();
let inference = probe_block_cbor_era(bytes.as_slice());
@ -81,7 +81,7 @@ mod tests {
#[test]
fn mary_block_detected() {
let block_str = include_str!("test_data/mary1.block");
let block_str = include_str!("../../test_data/mary1.block");
let bytes = hex::decode(block_str).unwrap();
let inference = probe_block_cbor_era(bytes.as_slice());
@ -91,7 +91,7 @@ mod tests {
#[test]
fn alonzo_block_detected() {
let block_str = include_str!("test_data/alonzo1.block");
let block_str = include_str!("../../test_data/alonzo1.block");
let bytes = hex::decode(block_str).unwrap();
let inference = probe_block_cbor_era(bytes.as_slice());

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820284828f1a0044abcb1a0047967c58202398f79031da6f550bae3f1b632dd4bb368c27c12e32e6bd61f52edfc6eaae7d5820f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc85582022f9cecbecf3986953c01ea54260da2fe95b4293141c0712754def9c69ab6c9182584055c3eff59c04e744ae3c16aec6c3f5a551fd8e4f779971decbb6c7d2a3714aec1976264d4ee202ca369f29be932711c8bde63b34b64c06ed2f4e9ab5a1329e57585098c451df3d4a6e9159661fe29a8be2921adc0f103095bbc3d4035222017fcfa6ed04dc79b3fdc9427466a2466669f9fe4ae77fcd4aa8caa848d64ebc4d74586ff3c48a141b5b95e552ec3474f234f50a825840013c07946856242e4f93b3c422082d98982d9e231897d9ee8b59037cd29f6079bf91303b6da9564419ef8fd31a13b3ea6723ec45ec731b434069b375a99cb34f5850c49b9427372dca9828d6d77dbfa2f66e7b68601c4e63fb9ecb298615aa15d6d936069b6213818752819c9a9ea09a28eab4a6df8a7ba87fec95470a0853504b6816c13deb9ef25264db3a244b590306060358201033376be025cb705fd8dd02eda11cc73975a062b5d14ffd74d6ff69e69a2ff75820b6524ab310081164b67a9183be3759f11b018b802f06bb8a7c5d02ee6a7789e800005840868b538f654bde3c98cbc29fbb6fa5d2a9f89bb5f1804a91f0edd301cc1fdf03e1538e1babaa5358c788d81bfd06ad191d2300ef0a0a503ea39f68140ebfa00402005901c07ee89d8efe52849ab043d82ba20aef40c75a78d44ec02643f33ce19177e74bd400027829ec0238a0562babcaf530fb6fd3935438a3a08e1ffcc9094fcf3bd90f6612fe8771a42f65f08f51501180cd881f41e201514737568a83f895444d2541ef4d35a0646b292a1d1863f11939975cd7004407b0f0be050c1d01371e8e0d63e9a21d4a871208780002ac69ec5460b94f5ece69d8a35fa70559764004ac2ac07adceea64f61cc6142d8b46bed3ef7e207d0a558a594f8756aec1c4c23e312641f3a3019c0fa78df9d21cd1596e440b7d928c99964edde0eff1cf1da45352b11e3cb73bc6be058b80329f8d8e870d85dbba84f0e5b52c86384617561a542b3cdc4b312522bb029fd798fcef53ef381b9bb7482930fafcaff501416fc83c73f1a353b7356605996f5e5308f4b8905926de5854617603b0fab1db252de195d6ebc3d2b2f5d0d2396ba8a35513b3e1d8c8607717606122ad05ca50c93fc4437889ea4a4d2c3a273a0466970f8cc86edeac65aaf6092b6b6f581f455bd0bc4ad80d3cbd8f37a07f076439e0e9385795d4185603419eee6018bbb237cccf827aab2214c2dac5ef86714648ca654ab93b34e7478c6814419970eae26d5a50dade111b88080a0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820484828f1a0025c5711a0166339b5820910ba37352a06e5e159b82d487ad708267cdf57bb8121d13c244ebcf2b0ab9ab58201ec8d999a61a9f3df823443b3f4e2ccfda2e618e4948f9da5d3b3c6ffc7dbd8f5820532ce456c313aba1789e04b09212e334b46ade690df146cdeca7d44cb80940b082584094b455f5171bf1769d9b08d730056e2dc408985945ee6efa2aa84e865e7df1749f9b3e0d0ad81bb3738d181bdb09787dd3b176da4270ac59fa3d06f383cfb6465850f1ae2e5d902b4847a1357415b16b50e65ae58276f1636d5ab9b0c25a2a5673bf446162693b7a200941a0fedb2daf512dc285f8afd671edaf274ead52470293e84b33b170f4a35edeaa71190e30bfc80082584000047cd2d5f6818c046d491a4ad609dd8f6c26d7eaa7aa86feb87fee16fae8ec3ca12dc2a083dbb5efbf5ca5693dd1fb04a17ad03ec55e70441f1e720d7287765850d3707f09a729b9c5fdf44170e4ef4129a4992b5951733d43a5e112310360fb9c4facab304f8d8cfd327ce4117b11483320f335835a69d58bb1648276a5637c1b51317563f57463c590f770fc21bf3e0319026c58206fdf6f9c0dda0aa285fbb9910f18e3efd5ca638cb89310327abe250a79d04b2558206210669b9f6f22b3ff77e9f29fb247b4499074a892d33c7c129f0bbef77efb9001187c5840c581333e0ab1c9209679485b5d335ae6ae09cad634dd6251b911de9202e43f39ae939a02841bd2580799b0a8795421216268d0429580c4f1cbb905e913fabf0a04005901c0f1061da4762609e857a92077fd43c3ce80bcbc6b4c750ceca4ffa18fd329a92a396816154b6c12faaf3c5ca4c1e8c5ce78199fabd1a3d13b81a5813289a68b013f34e4c9df98b141c39f90f77f5f1c7078b13ccddbc29b90c8ead897a72db1dec69505d9ba27274646f8cb00d9047ee424167cc19a005b3313c6c9a908ee048e37405748bcaa6fdf41c8fe7d4d6988ca0e860b148a898ae70b23ab563f726463b24e2ec8319d3612b3e8078791c0a12cd7f658778b6c7fd0be58a220e68d1170d7436f7342d3030d2d36421ead55a47951a73a140a77de07e2d4653df961d383ba942a3c962831430f47b991107fc589ad76ba7d4d4a9397cb56037a90925b6ece3c12d886ac7fd9126ee8ae620a15503fa590273fe3d3b9cec5ef360ba0d533b58ec1d04b5ed3c2a49a4e7f7c403cfd28df154e217041d5fc47a306681e2698569c98cbba5bd55dc01f936a1e34f1b1d11ce4e3165478f796c061121471c9ed223010cbf7a19541e338153267dce239e5173f4692cddfdee4ae90d5a179a7f42928be872c2dbe55f7488366ac1658662e242c6bc8027d1c8516668321f51e3dc5e373006ba466455dbfc737e0b8846fc5048ccc4559c4eade8d4262a614f61681a600818258203d89ceca963d891e974728f5ae8d80a6da13bdc75755c4871c9773a0c0a1303100018182583900d20826af8f21d9a1560e994bc6ca05f01dafdf12f87dd62b3ce0af4b80d36c838e0f562b7ceb4f9db5341feb5252f50751010d6bf499afb6821a3b97e763a1581c42871c20fdffff1cc1587f2c12aed2dcdd0f6c7eef5db3856ed75646a1456b636f696e1901f4021a0002e29d031a016635b6075820e4d7330107502587bfaf5b6f842281aec3bb1f66cc7011db575b1e2dbe51543709a1581c42871c20fdffff1cc1587f2c12aed2dcdd0f6c7eef5db3856ed75646a1456b636f696e1901f481a20082825820e6cbcf07bfae01c353dd6fa2011069f752d3ef02a08383635c267a5a3e982cc6584054eb58b8f58d9b79b02c92bbbc9347f925d9da09ac9c5633b090aa8222df5e9577c44635ef037dfe3431cb69353fab4bba4ba0a96d814c33a98ce57a97aa2601825820db5672beeac25c232773da584890aa54f790b2f625e0031d6a958b5d324bd4ab5840b1ba2b028812db166e6f7c7844070c94ae337c074e190e8659133ba569cea9c12874b5b11b6d8c229ee19072497490d9cb1afec97d600bea5ab1ec0c082f750101818200581c49fbb538dffcab1f954a972de32015520c0ef9011413b0dc854f75eba10082a61b0d205105e6e7bacf504ebc4ea3b43bb0cc76bb326f17a30d8f1b12127f810d7dcee28264554a42333be153691687de9cad1b12c2c4e58b6778f6a2410e463bdefda922654314ff8d3bb6597a178e6a15261b64f4d10bda83efe33bcd995b2806a1d75f1b6827b4dcb50c5c0b71726365486c5578586c576d5a4a637859641bf710c72e671fae4ba080

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820585828f1a002d60261a02570a2b5820fac5eed79d1e1c780539d480ff073b7f122e133229a54beeaf737586354b69125820fc0fb919a58153bf14d52123172905b65fb865e080ef21aa2f4facb4ba4f6f975820435f451a0900e4316a38814b869c1d7d69a609bd3f67cb2bbb37eeb948bbcac7825840b2063104e15befbcd5c61c22089a913830adcfc3a76e8b5ac329aadd8c2a945afa59811bf0593a0738f46f24f68ce2f97455e774f60a6c8182a023785575d34c58502278d86f7bdbe5d882fe64861c12768374a700990c27bf2c08aad88f6afe951ac0effb2450b5681674e1f2eb23ba2317b3b3e614a9e1143edee68593a77e46d60cb8853ca148364328b6491b00c4d80e8258400001d94b59029d14da2fe37465b0febe7bcfad6c6421505367d9c7c5a0ecee689ef9734d5390a0f9769e7f33ee92fc650dbebd1109c4f6ff2591229c9eeeab0358507ad175fcd88161ccde76729654d470a2f53621e3a65d6860acef74d7afb7de21e35ff3ca95106da5664693a148d747c2ff2a598e334892a4ecd6c8fc436276b07d9364a6f277d5ad61f2ab3ca93aaa0a1902e1582019aed974f28b578ce4f0b769683098c9be065832cb6ea90c8020707336f763b258206533bb86ad398936ce158cb93c8250e912817b841b9f415442eebfa59a2f79840519012c5840eb0299940d21eeb88a2f790dee5cc3fff58a993d9940b3c9b50df077cae995478a8e57905a84c7061aba103426008f7640a87f6d97daa62f9a28d69198d57b0206005901c02654267f21634ca2dce897467962788a324622f2bea0e51db8772481020c2ed45f896c5720fba47625ef82ac56e6a52a1e55b00076a08b59d83e6606a0708d0a3735b3e76a30894f631d30c58138bfcd31c17785df7350ec7064af324b0444928d1d39d5cf6b12acac0420adccceca563129bb5bb4eb031e22502d264e6c24d7ed7b6b61fb17270788c010fd6babfbfbe3abb14a61828504f66693a397c5d36a1b605e2bb80a980cb6665c7ddf534a0c8bb8dc6f2b4ff28787286d1ea5daed7b8d1e8bbaedf58962fd8e03dc09a31e3847f83aac1da0b18c73cb75d834a62953e2df1fa1ea1a142d11e05790fed46ffdc8dae04cecb8e87f76ece5bea1b0757f796fcb4d4c2ccf72b6517c21c7226ecc110d3f08577466b3631fba1a799a4ef9d637bf133abc1c338a046f1236a2999024bef15ccea0f2ee6cfbd6dde4dc972cb05f7e4b302ae4edb397b240e7248df1cc9e276e392675c1db5a9bdc8a443b2434df83d485cb7cb7f53762e113e8dc76d9901cd3ffd306c9e379946ebd6084f2bb42d6b47e28fc28b6c6c35413d59eeddd025630dcb410486d2aa05f9fa1cbcbba464ebffdfc2abbcda25e1201e1a7eee390a493a95d30f9f61a39fd2c3d0e6382a60081825820a3d2154beb116d2aa88e49f17ff9dbace9352b9582e0e0e8a7a16ebdeab732250e0d800182825839006529073eac50d4bbae76e20c1297d4db7a26ee357e882ed50d3c4f12323300afdf4ee71d4e3e81693af20a2b37181584e46683bbf3de40271a000f424082583900fbadf9cc4f26b7ec96275cea654be0518842c4aab517cab185db3b860621e5bb147d0cb7cb2b3ec2770bc15e1d606f2ecf047a9b2e49f4941a05e40a83021a0002943d031a025726060e80a60082825820908c5c76d5cd7bca57811cb4a23cb32144fb7d0e3901d57a263a12a654e6de9f01825820f3a7e07064baae4071d17cc48f13203bb89d75d16357b8d2f1962ccf8ba4098f000d81825820f3a7e07064baae4071d17cc48f13203bb89d75d16357b8d2f1962ccf8ba4098f00018282581d6029b16af84825019ccb5befbe368541aab8f50dd10009c8491e78374a1a00c3b70d83583900ee4ecec389996991d14256d8361c63de83b08d7ea15d083360febe1e6bc484df62d1cd81f428e2644d260a9501d2cb38d3a4caabca00a87a1a0016201058203fac877e3f1eaefb3cbb71eb8d49248b51571fd18dc02e74f464f038eb734935021a0002bdd60e800b582059fb4246b139aa89802594f2f94a0303ba525601cda8905fc83cae2a6e0bd1ce82a100818258209d0b2238a80193022d9a3d8158963709c808861b1aec9d65ecf5c2f8783c050058406a917825516e37071266183801a1acd1eb5643764c2511ce0963d3de71732204da2e0b6e4d1f97faa5159cfa03c9e0e5382b9321ca915c213a020ef8e082760aa40081825820bb8d928f037b083097087e0bed1cc6fb5714d4e219058469197c5544dae5f6c65840c04ddec1bd428cedc5a0e6ab2a0b574cad8f235346f5ec6f3ae71a684c54bcc39eeebfc522dccd3d393b5f3767f547b3565615a3ac9b4bd95b7b7c73fbdb720303814e4d0100003322222005120012001104811bffffffffffffffff0581840000182a821906a41a00074534a080

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820484828f1a002537781a01550c6758200a4bea77c82dc4641df52eb7b48131b5b380b0b8b85cdcc461ce463d582a16fa58209e32d6447bb62e5f13ce769ed0cd1862e2433f3b707cf0240fbd094e60763c6c5820fc2fcf18fa5faaf84f6ecac787e8694e2b2de64ff649bb14b0cc141ec267b298825840e8eb1c57331951d2b3de280b753a6ba5691b8cbcc0d5af7769df37285b70666d304317f44f1b930df097f5147fb7332b8ff7e5699a2206543eacf4a86d35444d5850e1c157310aaee3362bc858bbef4a8e79668df1347c9e316da156400e6f3cf61776c9662b694e14f092625e80eb3f7587310fe9b0a067bd133a4113d435a40828ad3d42921a1c9b89c5b984275fd4070b8258400024acbc27df2d82af0eef2b5d72da906eb3add3531ae595d68800dc2f55688f622459e5b0305c2fd8ea1577d0b8168e37d29a63c0f95c2022e36c6d5edebc8d58503543def2d5f95c37ed7c34915d41ced53f4b41f4e785ab5922bcc4fa23e240d06908c5bc82921c98815be5c1a718167fd76440e7cccd5cf6bd1bc61be2626be5006b25a0c44cf14dc1fd294e0dee690e19016c5820c23a5dae88c44be3926023def87880abde35c6dfd969a5b866ddce1d61044375582043cc179ab51c985bc00d7a346ffb4d2d661221fef106e31cfe17c37555d5bba90118a65840443e5f302bde78e1a6b34175c6be5dd9e037f74893dcf7883c50eca647f7e3d0c5e1dcb7ce347ce57eb7fb5eaf0773d79a8d6c01a3ea00a9b1b4f14e3f24700804005901c039aa67d82106fa79a5a1a99255790aaa93918119d677c39713978bb944fa08df1ff309aa8ee8fa954ee44d3167141ef896c553b1e6e039323c190f6ed23c950e3f9cca8521178fb7891a5c17a1efe8a18c53c92caef5ba5903a1a97e5e3b0c1d3369a22906be1c9ddeef64c7e8013da51132f255803047a4f92c823f67bbcfc6468c645e48992a0c2b9987242f0b470506933afb41d9b789f0edf5ede3b36e237cfd6f30dea7e9232c560f86ae38b0846b878d788e357cd90a332be3684e1d28b7716d8a3fbc6701a5cf7231fb4c23da03bbee3006d685b7b6dc524e1af293526600ddb52fe677b88890689ca824e4ae4a3d9ad942e5bc9c8f33fa6de20080f84a3f23ff094ca63c0c0cf37dc9f44c3e517872d53c6992d3daa9b73b5212215d85bd39fc3bf3bd5b80c38aa726dc0b392bbb37a29ae7339eacfa8cd79f35dc13dc4879958af6b114853e906ccbd2042d2f5e3ee68202a43f1d60c80f515b7e54c557e85aba025e33b1bb277f2d423f5db6bfc5faa96723e3884a7d1ce5a107e2686e66cbba4d4ae850329575a10d0c93ac02ea187285d77a1f0761746042e180174fe8fbdd6b4c052ae9d9b6d2be98c5ba003b4bfa322bbb6e21029305defd0381a500819f58204a8c8c2c5339bd9eca64cb1980ef1b8ecea86b285ddf270217f9acc274e42fb500ff018182583900ee8fb6f212bcd2a2970dc0ae54f02ba15412c89b6c5a6a812003b94bca18550fa36e175ce66ca2b5844691b77c90bb1d538451dea2cb40821a3b793840021a00030d40031a05f5e0ff049f82008200581cca18550fa36e175ce66ca2b5844691b77c90bb1d538451dea2cb4082ff81a10082825820a1d4002d0249d00d50232ddb94c91e5f8ba0a052b6d2d29c5e143ff4259246645840a3d7c4746b4431998a7a3edda41e2815c7fca6d54cdb07c6865350be19641594621b8d8fdba5511afae4e10b40bfa55b308d3522e021d2bf3d3013ab5cd9e00a825820f33bf4dc8b9148aa717392b8f8f7ce47b7fd682efe92e6ce7229367948df3c185840ed43ead57da35edc82b0d214d052da2fafe57e8aa33144b0b52447c709bf1abe9f80a9de3d75352f8b8dabad57f9e074d90035430ba4e61554decc597833060ba0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820585828f1a002f4a4c1a029629ad58205ad2f2deceaccd8146b93759d0fa67991651ca839144e64003be26286d1d378e58209b30232b87e5568f4dd9848a0ea9d91fef54ba11bcd39121cef5e7e6e750f1575820fae4b8f31c676f58a039005d59ea1d2179a83ed2e1f0707b46c2f6c4401d7206825840cf0f48ee58294f1e576a94158d2874d1502116e0cc6a645968c0338e453d774fae0759e2f20d77d413e00c9aa9aaeac090dcbc71a02eb5a15dcb8390bec5e67a585033f146522cf11b4df9382b37b1ea4630bf270317cab1d7c957273426777ae0e4e7d6d700cfec44380a1958dbbee09055b84fcf4b40d506c0ec4c620c005737a250297b877431405eb77c36beee74fa058258400068ee9ea93d139ecca4a7a4ecd9e18c0e233c08149e75080bbbe7b5aac6e3280236d703a9afd93513e972dbaa063c05356512e74c81612d5c9e0436038567fb58500b1bf104008ff1ed4cbb8aeaba933e0a06a0f117dedd8a6f13f6bf62cb00c2225461a88c4e92d9d4b5ab109d58416a76e23d28f36c7d3878e7b16fffa61fb66dea0fbabbc42677f557c3f38384f0d4071904285820d392fb9117513610ab841a17327bc28572cc1fbf47eeaf494917e664d3d014b15820b4590f50ac87d2b4349ba2166b0127c0c78243907e908e6fedb40aedd4b93d7c061901485840b8f3a384c3c4fc4ba055fe96fd152955c04657f84bb5486699222dd2f165f47ce28d8c16cee5df37a6157eb03feadf8318726708af24aa7a4e8115e8cce3790e06005901c0c889981b5e3e242be0d9bc74d7e3cdbb9f1ffd59a11fe2256ee6f66b3c7bf575a847fcdf6899fa14e94bf80da25544c33a21b4fe75166dcef427c97c5386b00b97abfc1a062248aab0ac49054ff3c7de07978850417da22248c31d1c500c92de762ded2c4bf896ff46b16a1cf4f67a4c9e805b25f1286a411e4f29ab1142d988d75a68cc52261d255e7a639917df4dcf04b0b6266e99470f184aa9284e2339138b0bfcf460d558db50c0cd213347db35a13d47dadcffad568e944a70a0a9f2ea34e6cf313d355acf01838f5a0e39afd5ac832a376d03bcb8fbd9f51b75dcfda1a70194842f9793606ba2fefc63fd35fc7032c64887be82b257645b200e0cce00cff671e5444910b85a119970affd8a6121fd07dfdf7482255092025233aba620973f083ffb6b3e1310a8f96573bc117d38827deeea18dd62b44e660fea3dd94cae33bed669d40bd4af7d6cf0e64043a09f3a300932814749610f8e5c66438a7aa6ae5bf662dc81b1fa2b586b2048b0ed8d714c667f5ffd8579919942c64032bb0221b5fcb7625aca20ec2b1c0d189a37db5c03e613234739506d595980a06543e4746a7e82f6ab2e816f13d6d02aa26ab1bba65585fa700dc42b08609075f79f81a600838258204cf7df47e1aa8303380aa4dde4b83545c48e6094fea6735a9885e9e784e6d80d01825820ca60ad59ae9df6b3188d9c6b8545723a973695e58dc5aab6c5edf3b6611a10b501825820cea4b3f0dd6d815cc028c0f6e790bf719f49c334108ca1014e4794fc59344093010d818258202bf219d87408a81b110567b01c8d3cc3fc7e17d4d3585a21587e6a4b454426f3000184825839008cc30a5608abf06060864e214441d9be2362692bc25fda12ee549fbdab0359580d253ffdfd5b7e57692fba68db312d184a23231c24f27c9b1a0098968082583900d34fecdda880807048625cbf1f09af024ab4694c9e45888d2a0de6045c76aa2fefc4b0c3886d2a2adef634ba9040ab91c64d16a224f5737d821a00155cc0a1581cd9a1156d008866951090923bb1d39587aaebb342c50e5fb848f5d84fa1445245563218c883581d7067f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656821a032d3579a1581cd9a1156d008866951090923bb1d39587aaebb342c50e5fb848f5d84fa247504f4f4c4e465401445245563219021c5820aef3b61d6806116a70ada02870f7717249252b70f117d7d2bf1d5e7d4487de25825839008cc30a5608abf06060864e214441d9be2362692bc25fda12ee549fbdab0359580d253ffdfd5b7e57692fba68db312d184a23231c24f27c9b821a00d59f80a1581cd9a1156d008866951090923bb1d39587aaebb342c50e5fb848f5d84fa14953776170546f6b656e1a00989748021a000322e70e800b58200d6e2523d69edd04bdf699a0d369fbc6d39076df73e4d15b2e2f1e20d290355581a4008182582054f1a5800650ab29f920cc05e5cf73bb64a0359c6952e78a8386a6ac4e320e8258403d1a117682859510ae27ee98bb89d24eac0a9dac605c2008a65e85df75de6c5682d0ba3944bd17a1ecfe1f8cf38160d1831a5e7889141e1b2871dfb6843af10703814e4d0100003322222005120012001104839f583f616464725f746573743177706e6c78763278763961397563766e767a71616b7765707a6c396c7478376a7a676d353361763265396e637634737973656d6d3840ff9f5840616464725f7465737431717a7876787a6a6b707a346c716372717365387a7a337a706d786c7a78636e66393070396c6b736a616532666c306474716476347372582c6639386c376c366b6d373261356a6c776e676d76636a36787a32797633336366386a306a64736574666c656bff9f5840616464725f7465737431717266356c6d7861347a716771757a6776667774373863663475707934647266666a3079747a79643967783776707a757736347a6c6d582c37796b727063736d663239743030766439366a7071326879777866357432796638347764377364776c727474ff05838400001864821906a41a0007453484000101821906a41a000745348400021864821906a41a00074534a080

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,4 +0,0 @@
{"constructor":0,"fields":[{"bytes":"11f76aa14dae8aa6ac6578af2287bfc4c8e7a3da566548da747e026c"},{"int":250000000},{"bytes":"c56d4cceb8a8550534968e1bf165137ca41e908d2d780cc1402079bd"},{"bytes":"4368696c6c65644b6f6e6734373636"},{"bytes":"1656abe748903d4610c6db6373f036c8aec1b19ece5c93b6f25b5233"},{"int":30}]}
{"constructor":0,"fields":[{"bytes":"11f76aa14dae8aa6ac6578af2287bfc4c8e7a3da566548da747e026c"},{"int":190000000},{"bytes":"c56d4cceb8a8550534968e1bf165137ca41e908d2d780cc1402079bd"},{"bytes":"4368696c6c65644b6f6e6734373636"},{"bytes":"1656abe748903d4610c6db6373f036c8aec1b19ece5c93b6f25b5233"},{"int":30}]}
{"constructor":0,"fields":[{"bytes":"92f5aef1645f377ce472eb092ac8a572f9811d3ab2d5dd39cbe07064"},{"int":380000000},{"bytes":"bff82d31352d9bdfdb49e243ab74af715488631f330b2cf064178f90"},{"bytes":"426c6f636b4f776c734269747479303833"},{"bytes":"68b82dc4fb2d515501728de5bfcb1fd0a47eb3dd628d3340e10afa28"},{"biguint":"00"}]}
{"constructor":0,"fields":[{"bytes":"92f5aef1645f377ce472eb092ac8a572f9811d3ab2d5dd39cbe07064"},{"int":350000000},{"bytes":"bff82d31352d9bdfdb49e243ab74af715488631f330b2cf064178f90"},{"bytes":"426c6f636b4f776c734269747479303833"},{"bytes":"68b82dc4fb2d515501728de5bfcb1fd0a47eb3dd628d3340e10afa28"},{"biguint":"00"}]}

View file

@ -1 +0,0 @@
{"scripts":[{"keyHash":"4d04380dcb9fbad5aff8e2f4e19394ef4e5e11b37932838f01984a12","type":"sig"},{"slot":112500819,"type":"before"}],"type":"all"}

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
820284828f1a004723dd1a007949425820c175f470d30216341423a98a6087175642250acec7d9f53a311cf2e0a1c9c7b258208b53207629f9a30e4b2015044f337c01735abe67243c19470c9dae8c7b732798582090561cf5fb4eada778f0564060b9b5138fbfa50c0e74fc496956c8c3507301a6825840d266d923d59fc8a1b7e964dab2b6db804b494c202586eae8e2db929ca2361d9f01154c4a78b95a2e6bf19ebe98e775f894ad53971bd1ceeee125ee8473747d60585011614e11e284d28aa303da9ca3a37bfde35f931d308ae3da36e381ac42910d36dc26d91bfa726d7b4a7ae1fb263e037e8f9e80e3411a8754863b8b5601047b9e04d0f72f00206ea616c6cffc75fc48018258405620f9239d562aed34442b72c8bc840bb9a5ef897b470132430a02cd0ce69052a6ebb17896177180c1d88afed3d7614878549c5573c0f281d5dad2f29bda5a6d5850f349597045cc5f65a9724770f971e6964e09fd85db8e36ef789f390afd4629a3f5e96b4e5ee8280ec26236a6323cbc16867a1868645566e0607d7a474fd7d06b44c3afbcd85a41098a80ba6faeb7400b190596582000ef8e1bebe7d404a910c7c467fb5aafbc7dee7fcaac94cb9693e08ea9dd7d2a5820674617ebe299bcba144026e4342e9f54c861165c1dde1373fd1206e654f985b800183758405befdeffa73bc8b4a1cd22aa2c896f189a698175e5bfc4a562e3a15b5f6580953e6fcc72a37386816031e36fdf19718351417f01af02c7314fbe9f2792b29e0c02005901c0c597caba74923b7901d5b8162f27338413b12941e411e9371b06a01375b8690aab067a42dde22db909bf77db373ca8645b751711256ba5f360e2935f64d14104cfdfb6c7865c6f4219e67af060cdcf4dc3d874ede00c394e9ecac7ba1f663b367e0f482e1bfaff08808d6567590cd6bf43c849ebacfb5fb185f4592ff3bf0a479d5a1f3f19f819b59f662cad2b6ff2187ec94b4c5fac6b8375b02d6b52d229ae24b389ff2d72b584f47f77cbc62a43f1880e486fda30ac1600f475dc4857e66090fe7399f4e3bff4929ea1c1929371846a34391473c79f9409f05f65fe8d2acb6f5eceb84474555d163db96d809aa77b9c2f80156d0356e75204ab5032e833bbacecf407038c8a28da4900c1c63a5bb32672dd345c37e1c866b15da5d2c41ab76c214bc8e3efd9e34cf092f1166edc2de2b03ccaca01b2c0261bfaf3f166f3937c21128c3ebb96ceefab6c80897da9f096a7cc113c4b9c0cd8b97fe3d29f6a2c9960005d2f1ce2e8bfeca9b1f8ebe80637f59133692e11ad9f9c557c10102472aef7f472d72920bbff7a7f4e344988c2d5f98482fbbae7a081d7f10b55b33a7c4dea90483223bea2093cb068b2db39973dd06700ea4eb65fa3210d7d53430c9c84a5008182582050eba65e73c8c5f7b09f4ea28cf15dce169f3d1c322ca3deff03725f51518bb200018182583901f53fd6f6b96f74cc90fd995afad1bfdbd49ff7d04fc9e7a2f81285b75c465cbf8c5536970e8a29bb7adcda0d663b20007d481813694c64ef1b0000021f05a734bb021a0002a389031a0079652c048183028200581c5c465cbf8c5536970e8a29bb7adcda0d663b20007d481813694c64ef581c6b5180a258275c671690c94c704f074190e90ea900ed565b4c29abe8a50081825820368f24c09763ee846f68c60f987eeca4d9a7e9cb537cea2cc593e77dd9c0ac67000181825839019a5d1ab9ca1eb592973a0d3f5ffdd006e7e4c0be6a7b43211325168932dd8b472ba9876597a01259896cdb4650a62402aa9737175d539fe81b00000045d92911df021a0002a389031a0079652c048183028200581c32dd8b472ba9876597a01259896cdb4650a62402aa9737175d539fe8581c76e80e1b3f622c7051f222453497b0667e12892f5d94ee565d17dc52a40081825820cffac1e93f583d1f272142df5b793666e613c66cea4e500b18437aded85febbc00018282581d614497e18047e5c891ead6a215b3f5dce026921a8b76c7fe27a2ba9f681a000f424082583901a76b7122a3773792b6275c9a0fb0bf4ae0c17c52363de66062eca50c13ce7fae17ab762c4390c4d77bd74f7d4651af480508ea237b1dd0b51a0086a7f3021a0002ac4d031a007950a4a400828258201c3b9c2016d9ae6b3e86e1888296e6bc180e6bcfd344711b7305651ae90f87e60182582038d2f2cf6a2ce8563cc3b84b4b0e003404363a352fe1ac7ef5a6b5bb014c3d6c07018282582b82d818582183581c5f6712df165e03b5eb5e72e50058a181777696b222c54d844944da14a0001add85ea5a1a22dad5bd82581d614db3b10bedda3b9dd3d3a8886ca9d8a581162b874a7460edaab406fb1a032fcbef021a0003447f031a0098968084a10082825820e3968f45134a774f66b011c2c463ad64a5ba7e17f4774be460d08477a07e31f458402c551fc904b8e55a58d437e744566d0307a186af8f08d51a637456e0eb8247a0b639441a4fb25807b46edd60766a9e766b19e7c33caf5eea1752fc017b840100825820590a7c4229d9aede28c43f2626fcd36bc383cc3e622a654ad962e4c49570938c584042f3ed22755c5523a66864cb644330b82ace0b7cd483f4ea4e4c4d3ff88e62785811bf6a7da08e386f218301ff50bf8d000ca3df07dd831b9160b469ac95110ca10082825820feef653d2ba57531b9a442258cc0ad12feda29141b3e2a05e4a037262c4bb34d5840def966f7d8ea6e9ceb519606a9b7076b85677b6edcebd386f42f71c5c942c6ef90cbfad2265634cf5ebae00f8b86760151c6559bc82b52c130547eed5414120b825820d91dc0521946003bc7ded1a54938a04bee80a860382c51ef7c9e4563346979345840ab999c3cbb8edd48da9b884a4dcb86a8e7b7110ee08f312264a018fa6d50e4a0635f124916be7773c38c8bec8a0fa7f2ac5058a776932ebfd557a8a263552409a100818258205ee8a66efac254382955ec4d643a9f24015d0ac1ed32480b1b7235f10e87a0e458400fc033349c1a9ecf966902e05f35b7459a642f7b3818c80003b08179631521c810a8a52e30c5211a38a88732369fdf07d96c83963564f11b14048c060a2d410ea10082825820a1ecd258e4f23d09803873e6b8a5ed21107738e12004ed7b1fe1bf89c9c49e5a5840789070b47a7d4bf6ee4d56773ace2faaed2f76905848d65e5c35bfb75339060ec9c6e904b9a8fc54cf861a6da4aa3d8f607cb325b1f1cc266e49fb8a6dc3ef01825820a1ecd258e4f23d09803873e6b8a5ed21107738e12004ed7b1fe1bf89c9c49e5a5840789070b47a7d4bf6ee4d56773ace2faaed2f76905848d65e5c35bfb75339060ec9c6e904b9a8fc54cf861a6da4aa3d8f607cb325b1f1cc266e49fb8a6dc3ef01a0