From eda83ebe0e0fa31daf8a5b2290efd7bc2e495e95 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Tue, 16 Nov 2021 22:26:15 -0500 Subject: [PATCH] Async Halo2 verifier service (#2645) * First pass at async Halo2 verification service Stubs out a batch verifier for the future. The dependencies for orchard, halo2, librustzcash, zcash_primitives, have not been resolved. * Halo2 verifier service and test * Remove redundant conversion * Test async halo2 verifier service with pre-computed Orchard shielded data test vectors * Fix typo Co-authored-by: Conrado Gouvea * Assert future result is_ok() in Halo2 verifier test Co-authored-by: Janito Vaqueiro Ferreira Filho * Shorten tower::Service trait constraints for Halo2 verifier tests * Remove commented out trait constraints * .expect() vs .unwrap() to parse orchard::redpallas::VerificationKey * Use .to_vec() for some test vectors * Fix self-referential Display impl * Fix deps * Distinguish orchard vs zebra_chain::orchard imports * Add test that halo2 verifier fails with malformed proof inputs * Use thiserror for Halo2Error * Use ZcashFoundation/orchard instead of dconnolly/orchard * Add a link to the issue to remove the zfnd fork of orchard crate * Update zebra-consensus/Cargo.toml Co-authored-by: teor * Add note * Move artificial Orchard shielded data test vectors to zebra-test * Align brackets * Tidy some trait constraints and debug statements Co-authored-by: Janito Vaqueiro Ferreira Filho Co-authored-by: Conrado Gouvea Co-authored-by: Janito Vaqueiro Ferreira Filho Co-authored-by: teor --- Cargo.lock | 4 +- Cargo.toml | 4 +- zebra-chain/Cargo.toml | 2 +- zebra-chain/src/orchard/keys.rs | 6 + zebra-chain/src/orchard/note/ciphertexts.rs | 48 ++- zebra-chain/src/sapling/note/ciphertexts.rs | 4 +- zebra-consensus/Cargo.toml | 6 +- zebra-consensus/src/primitives.rs | 1 + zebra-consensus/src/primitives/halo2.rs | 274 ++++++++++++++++++ zebra-consensus/src/primitives/halo2/tests.rs | 234 +++++++++++++++ .../src/primitives/halo2/tests/vectors.rs | 5 + zebra-consensus/src/transaction/tests.rs | 41 ++- zebra-test/src/vectors.rs | 2 + .../src/vectors/orchard-shielded-data-1.txt | 1 + .../src/vectors/orchard-shielded-data-2.txt | 1 + .../src/vectors/orchard-shielded-data-3.txt | 1 + .../src/vectors/orchard-shielded-data-4.txt | 1 + .../src/vectors/orchard_shielded_data.rs | 34 +++ 18 files changed, 635 insertions(+), 34 deletions(-) create mode 100644 zebra-consensus/src/primitives/halo2.rs create mode 100644 zebra-consensus/src/primitives/halo2/tests.rs create mode 100644 zebra-consensus/src/primitives/halo2/tests/vectors.rs create mode 100644 zebra-test/src/vectors/orchard-shielded-data-1.txt create mode 100644 zebra-test/src/vectors/orchard-shielded-data-2.txt create mode 100644 zebra-test/src/vectors/orchard-shielded-data-3.txt create mode 100644 zebra-test/src/vectors/orchard-shielded-data-4.txt create mode 100644 zebra-test/src/vectors/orchard_shielded_data.rs diff --git a/Cargo.lock b/Cargo.lock index 541d2594dec..732fad37335 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2142,7 +2142,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "orchard" version = "0.0.0" -source = "git+https://github.com/zcash/orchard.git?rev=2c8241f25b943aa05203eacf9905db117c69bd29#2c8241f25b943aa05203eacf9905db117c69bd29" +source = "git+https://github.com/ZcashFoundation/orchard.git?rev=568e24cd5f129158375d7ac7d98c89ebff4f982f#568e24cd5f129158375d7ac7d98c89ebff4f982f" dependencies = [ "aes", "arrayvec 0.7.1", @@ -4375,10 +4375,12 @@ dependencies = [ "futures", "futures-util", "halo2", + "hex", "jubjub 0.8.0", "lazy_static", "metrics", "once_cell", + "orchard", "proptest", "proptest-derive", "rand 0.7.3", diff --git a/Cargo.toml b/Cargo.toml index 1300942fdc5..68f9b2451d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,8 @@ panic = "abort" # TODO: remove these after a new librustzcash release. # These are librustzcash requirements specified in its workspace Cargo.toml that we must replicate here incrementalmerkletree = { git = "https://github.com/zcash/incrementalmerkletree", rev = "b7bd6246122a6e9ace8edb51553fbf5228906cbb" } -orchard = { git = "https://github.com/zcash/orchard.git", rev = "2c8241f25b943aa05203eacf9905db117c69bd29" } +# TODO: replace with upstream orchard when these changes are merged +# https://github.com/ZcashFoundation/zebra/issues/3056 +orchard = { git = "https://github.com/ZcashFoundation/orchard.git", rev = "568e24cd5f129158375d7ac7d98c89ebff4f982f" } zcash_note_encryption = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" } zcash_primitives = { git = "https://github.com/zcash/librustzcash.git", rev = "53d0a51d33a421cb76d3e3124d1e4c1c9036068e" } diff --git a/zebra-chain/Cargo.toml b/zebra-chain/Cargo.toml index 57fa4f9d7e7..2c89bba5300 100644 --- a/zebra-chain/Cargo.toml +++ b/zebra-chain/Cargo.toml @@ -33,7 +33,7 @@ hex = "0.4" incrementalmerkletree = "0.1.0" jubjub = "0.8.0" lazy_static = "1.4.0" -orchard = { git = "https://github.com/zcash/orchard.git", rev = "2c8241f25b943aa05203eacf9905db117c69bd29" } +orchard = "0.0" rand_core = "0.6" ripemd160 = "0.9" secp256k1 = { version = "0.20.3", features = ["serde"] } diff --git a/zebra-chain/src/orchard/keys.rs b/zebra-chain/src/orchard/keys.rs index 4b877f7413d..73842b6de88 100644 --- a/zebra-chain/src/orchard/keys.rs +++ b/zebra-chain/src/orchard/keys.rs @@ -1064,6 +1064,12 @@ impl fmt::Debug for EphemeralPublicKey { impl Eq for EphemeralPublicKey {} +impl From for [u8; 32] { + fn from(epk: EphemeralPublicKey) -> [u8; 32] { + epk.0.to_bytes() + } +} + impl From<&EphemeralPublicKey> for [u8; 32] { fn from(epk: &EphemeralPublicKey) -> [u8; 32] { epk.0.to_bytes() diff --git a/zebra-chain/src/orchard/note/ciphertexts.rs b/zebra-chain/src/orchard/note/ciphertexts.rs index b858fbd4382..29a09a0c44e 100644 --- a/zebra-chain/src/orchard/note/ciphertexts.rs +++ b/zebra-chain/src/orchard/note/ciphertexts.rs @@ -6,15 +6,7 @@ use crate::serialization::{serde_helpers, SerializationError, ZcashDeserialize, /// /// Corresponds to the Orchard 'encCiphertext's #[derive(Deserialize, Serialize)] -pub struct EncryptedNote(#[serde(with = "serde_helpers::BigArray")] pub [u8; 580]); - -impl fmt::Debug for EncryptedNote { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("EncryptedNote") - .field(&hex::encode(&self.0[..])) - .finish() - } -} +pub struct EncryptedNote(#[serde(with = "serde_helpers::BigArray")] pub(crate) [u8; 580]); // These impls all only exist because of array length restrictions. // TODO: use const generics https://github.com/ZcashFoundation/zebra/issues/2042 @@ -29,14 +21,34 @@ impl Clone for EncryptedNote { } } +impl fmt::Debug for EncryptedNote { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("EncryptedNote") + .field(&hex::encode(&self.0[..])) + .finish() + } +} + +impl Eq for EncryptedNote {} + +impl From<[u8; 580]> for EncryptedNote { + fn from(bytes: [u8; 580]) -> Self { + EncryptedNote(bytes) + } +} + +impl From for [u8; 580] { + fn from(enc_ciphertext: EncryptedNote) -> Self { + enc_ciphertext.0 + } +} + impl PartialEq for EncryptedNote { fn eq(&self, other: &Self) -> bool { self.0[..] == other.0[..] } } -impl Eq for EncryptedNote {} - impl ZcashSerialize for EncryptedNote { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { writer.write_all(&self.0[..])?; @@ -56,7 +68,7 @@ impl ZcashDeserialize for EncryptedNote { /// /// Corresponds to Orchard's 'outCiphertext' #[derive(Deserialize, Serialize)] -pub struct WrappedNoteKey(#[serde(with = "serde_helpers::BigArray")] pub [u8; 80]); +pub struct WrappedNoteKey(#[serde(with = "serde_helpers::BigArray")] pub(crate) [u8; 80]); impl fmt::Debug for WrappedNoteKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -78,6 +90,18 @@ impl Clone for WrappedNoteKey { } } +impl From<[u8; 80]> for WrappedNoteKey { + fn from(bytes: [u8; 80]) -> Self { + WrappedNoteKey(bytes) + } +} + +impl From for [u8; 80] { + fn from(out_ciphertext: WrappedNoteKey) -> Self { + out_ciphertext.0 + } +} + impl PartialEq for WrappedNoteKey { fn eq(&self, other: &Self) -> bool { self.0[..] == other.0[..] diff --git a/zebra-chain/src/sapling/note/ciphertexts.rs b/zebra-chain/src/sapling/note/ciphertexts.rs index 5f7b975869e..9bdd443cf8c 100644 --- a/zebra-chain/src/sapling/note/ciphertexts.rs +++ b/zebra-chain/src/sapling/note/ciphertexts.rs @@ -6,7 +6,7 @@ use crate::serialization::{serde_helpers, SerializationError, ZcashDeserialize, /// /// Corresponds to the Sapling 'encCiphertext's #[derive(Deserialize, Serialize)] -pub struct EncryptedNote(#[serde(with = "serde_helpers::BigArray")] pub [u8; 580]); +pub struct EncryptedNote(#[serde(with = "serde_helpers::BigArray")] pub(crate) [u8; 580]); impl fmt::Debug for EncryptedNote { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -55,7 +55,7 @@ impl ZcashDeserialize for EncryptedNote { /// /// Corresponds to Sapling's 'outCiphertext' #[derive(Deserialize, Serialize)] -pub struct WrappedNoteKey(#[serde(with = "serde_helpers::BigArray")] pub [u8; 80]); +pub struct WrappedNoteKey(#[serde(with = "serde_helpers::BigArray")] pub(crate) [u8; 80]); impl fmt::Debug for WrappedNoteKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index 45704f165bc..bf2d2bd489b 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -15,9 +15,13 @@ bellman = "0.11.1" bls12_381 = "0.6.0" chrono = "0.4.19" displaydoc = "0.2.2" +halo2 = "=0.1.0-beta.1" jubjub = "0.8.0" lazy_static = "1.4.0" once_cell = "1.8" +# TODO: replace with upstream orchard when these changes are merged +# https://github.com/ZcashFoundation/zebra/issues/3056 +orchard = "0.0.0" rand = "0.8" serde = { version = "1", features = ["serde_derive"] } @@ -42,7 +46,7 @@ proptest-derive = { version = "0.3.0", optional = true } [dev-dependencies] color-eyre = "0.5.11" -halo2 = "=0.1.0-beta.1" +hex = "0.4.3" proptest = "0.10" proptest-derive = "0.3.0" rand07 = { package = "rand", version = "0.7" } diff --git a/zebra-consensus/src/primitives.rs b/zebra-consensus/src/primitives.rs index dd3fbab21db..ee25e718029 100644 --- a/zebra-consensus/src/primitives.rs +++ b/zebra-consensus/src/primitives.rs @@ -2,6 +2,7 @@ pub mod ed25519; pub mod groth16; +pub mod halo2; pub mod redjubjub; pub mod redpallas; diff --git a/zebra-consensus/src/primitives/halo2.rs b/zebra-consensus/src/primitives/halo2.rs new file mode 100644 index 00000000000..8f3cd3ce82d --- /dev/null +++ b/zebra-consensus/src/primitives/halo2.rs @@ -0,0 +1,274 @@ +//! Async Halo2 batch verifier service + +use std::{ + convert::TryFrom, + fmt, + future::Future, + mem, + pin::Pin, + task::{Context, Poll}, +}; + +use futures::future::{ready, Ready}; +use once_cell::sync::Lazy; +use orchard::circuit::VerifyingKey; +use rand::{thread_rng, CryptoRng, RngCore}; +use thiserror::Error; +use tokio::sync::broadcast::{channel, error::RecvError, Sender}; +use tower::{util::ServiceFn, Service}; +use tower_batch::{Batch, BatchControl}; +use tower_fallback::Fallback; + +#[cfg(test)] +mod tests; + +lazy_static::lazy_static! { + pub static ref VERIFYING_KEY: VerifyingKey = VerifyingKey::build(); +} + +// === TEMPORARY BATCH HALO2 SUBSTITUTE === +// +// These types are meant to be API compatible with the batch verification APIs +// in bellman::groth16::batch, reddsa::batch, redjubjub::batch, and +// ed25519-zebra::batch. Once Halo2 batch proof verification math and +// implementation is available, this code can be replaced with that. + +/// A Halo2 verification item, used as the request type of the service. +#[derive(Clone, Debug)] +pub struct Item { + instances: Vec, + proof: orchard::circuit::Proof, +} + +impl Item { + /// Perform non-batched verification of this `Item`. + /// + /// This is useful (in combination with `Item::clone`) for implementing + /// fallback logic when batch verification fails. + pub fn verify_single(&self, vk: &VerifyingKey) -> Result<(), halo2::plonk::Error> { + self.proof.verify(vk, &self.instances[..]) + } +} + +#[derive(Default)] +pub struct BatchVerifier { + queue: Vec, +} + +impl BatchVerifier { + pub fn queue(&mut self, item: Item) { + self.queue.push(item); + } + + pub fn verify( + self, + _rng: R, + vk: &VerifyingKey, + ) -> Result<(), halo2::plonk::Error> { + for item in self.queue { + item.verify_single(vk)?; + } + + Ok(()) + } +} + +// === END TEMPORARY BATCH HALO2 SUBSTITUTE === + +impl From for Item { + fn from(shielded_data: zebra_chain::orchard::ShieldedData) -> Item { + use orchard::{circuit, note, primitives::redpallas, tree, value}; + + let anchor = tree::Anchor::from_bytes(shielded_data.shared_anchor.into()).unwrap(); + + let enable_spend = shielded_data + .flags + .contains(zebra_chain::orchard::Flags::ENABLE_SPENDS); + let enable_output = shielded_data + .flags + .contains(zebra_chain::orchard::Flags::ENABLE_OUTPUTS); + + let instances = shielded_data + .actions() + .map(|action| { + circuit::Instance::from_parts( + anchor, + value::ValueCommitment::from_bytes(&action.cv.into()).unwrap(), + note::Nullifier::from_bytes(&action.nullifier.into()).unwrap(), + redpallas::VerificationKey::::try_from(<[u8; 32]>::from( + action.rk, + )) + .expect("should be a valid redpallas spendauth verification key"), + note::ExtractedNoteCommitment::from_bytes(&action.cm_x.into()).unwrap(), + enable_spend, + enable_output, + ) + }) + .collect(); + + Item { + instances, + proof: orchard::circuit::Proof::new(shielded_data.proof.0), + } + } +} + +/// An error that may occur when verifying [Halo2 proofs of Zcash Orchard Action +/// descriptions][actions]. +/// +/// [actions]: https://zips.z.cash/protocol/protocol.pdf#actiondesc +// TODO: if halo2::plonk::Error gets the std::error::Error trait derived on it, +// remove this and just wrap `halo2::plonk::Error` as an enum variant of +// `crate::transaction::Error`, which does the trait derivation via `thiserror` +#[derive(Clone, Debug, Error, Eq, PartialEq)] +pub enum Halo2Error { + #[error("the constraint system is not satisfied")] + ConstraintSystemFailure, + #[error("unknown Halo2 error")] + Other, +} + +impl From for Halo2Error { + fn from(err: halo2::plonk::Error) -> Halo2Error { + match err { + halo2::plonk::Error::ConstraintSystemFailure => Halo2Error::ConstraintSystemFailure, + _ => Halo2Error::Other, + } + } +} + +/// Global batch verification context for Halo2 proofs of Action statements. +/// +/// This service transparently batches contemporaneous proof verifications, +/// handling batch failures by falling back to individual verification. +/// +/// Note that making a `Service` call requires mutable access to the service, so +/// you should call `.clone()` on the global handle to create a local, mutable +/// handle. +#[allow(dead_code)] +pub static VERIFIER: Lazy< + Fallback, ServiceFn Ready>>>, +> = Lazy::new(|| { + Fallback::new( + Batch::new( + Verifier::new(&VERIFYING_KEY), + super::MAX_BATCH_SIZE, + super::MAX_BATCH_LATENCY, + ), + // We want to fallback to individual verification if batch verification + // fails, so we need a Service to use. The obvious way to do this would + // be to write a closure that returns an async block. But because we + // have to specify the type of a static, we need to be able to write the + // type of the closure and its return value, and both closures and async + // blocks have eldritch types whose names cannot be written. So instead, + // we use a Ready to avoid an async block and cast the closure to a + // function (which is possible because it doesn't capture any state). + tower::service_fn( + (|item: Item| ready(item.verify_single(&VERIFYING_KEY).map_err(Halo2Error::from))) + as fn(_) -> _, + ), + ) +}); + +/// Halo2 proof verifier implementation +/// +/// This is the core implementation for the batch verification logic of the +/// Halo2 verifier. It handles batching incoming requests, driving batches to +/// completion, and reporting results. +pub struct Verifier { + /// The sync Halo2 batch verifier. + batch: BatchVerifier, + // Making this 'static makes managing lifetimes much easier. + vk: &'static VerifyingKey, + /// Broadcast sender used to send the result of a batch verification to each + /// request source in the batch. + tx: Sender>, +} + +impl Verifier { + #[allow(dead_code)] + fn new(vk: &'static VerifyingKey) -> Self { + let batch = BatchVerifier::default(); + let (tx, _) = channel(super::BROADCAST_BUFFER_SIZE); + Self { batch, vk, tx } + } +} + +impl fmt::Debug for Verifier { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let name = "Verifier"; + f.debug_struct(name) + .field("batch", &"..") + .field("vk", &"..") + .field("tx", &self.tx) + .finish() + } +} + +impl Service> for Verifier { + type Response = (); + type Error = Halo2Error; + type Future = Pin> + Send + 'static>>; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: BatchControl) -> Self::Future { + match req { + BatchControl::Item(item) => { + tracing::trace!("got item"); + self.batch.queue(item); + let mut rx = self.tx.subscribe(); + Box::pin(async move { + match rx.recv().await { + Ok(result) => { + if result.is_ok() { + tracing::trace!(?result, "verified halo2 proof"); + metrics::counter!("proofs.halo2.verified", 1); + } else { + tracing::trace!(?result, "invalid halo2 proof"); + metrics::counter!("proofs.halo2.invalid", 1); + } + + result + } + Err(RecvError::Lagged(_)) => { + tracing::error!( + "missed channel updates, BROADCAST_BUFFER_SIZE is too low!!" + ); + // This is the enum variant that + // orchard::circuit::Proof.verify() returns on + // evaluation failure. + Err(Halo2Error::ConstraintSystemFailure) + } + Err(RecvError::Closed) => panic!("verifier was dropped without flushing"), + } + }) + } + + BatchControl::Flush => { + tracing::trace!("got flush command"); + let batch = mem::take(&mut self.batch); + let _ = self.tx.send( + batch + .verify(thread_rng(), self.vk) + .map_err(Halo2Error::from), + ); + Box::pin(async { Ok(()) }) + } + } + } +} + +impl Drop for Verifier { + fn drop(&mut self) { + // We need to flush the current batch in case there are still any pending futures. + let batch = mem::take(&mut self.batch); + let _ = self.tx.send( + batch + .verify(thread_rng(), self.vk) + .map_err(Halo2Error::from), + ); + } +} diff --git a/zebra-consensus/src/primitives/halo2/tests.rs b/zebra-consensus/src/primitives/halo2/tests.rs new file mode 100644 index 00000000000..1dd99b63d20 --- /dev/null +++ b/zebra-consensus/src/primitives/halo2/tests.rs @@ -0,0 +1,234 @@ +//! Tests for verifying simple Halo2 proofs with the async verifier + +use std::convert::TryInto; + +use futures::stream::{FuturesUnordered, StreamExt}; +use tower::ServiceExt; + +use halo2::{arithmetic::FieldExt, pasta::pallas}; +use orchard::{ + builder::Builder, + bundle::Flags, + circuit::ProvingKey, + keys::{FullViewingKey, SpendingKey}, + value::NoteValue, + Anchor, Bundle, +}; +use rand::rngs::OsRng; + +use zebra_chain::{ + orchard::ShieldedData, + serialization::{ZcashDeserializeInto, ZcashSerialize}, +}; + +use crate::primitives::halo2::*; + +#[allow(dead_code)] +fn generate_test_vectors() { + let proving_key = ProvingKey::build(); + + let rng = OsRng; + + let sk = SpendingKey::from_bytes([7; 32]).unwrap(); + let recipient = FullViewingKey::from(&sk).default_address(); + + let enable_spends = true; + let enable_outputs = true; + let flags = + zebra_chain::orchard::Flags::ENABLE_SPENDS | zebra_chain::orchard::Flags::ENABLE_OUTPUTS; + + let anchor_bytes = [0; 32]; + let note_value = 10; + + let shielded_data: Vec = (1..=4) + .map(|num_recipients| { + let mut builder = Builder::new( + Flags::from_parts(enable_spends, enable_outputs), + Anchor::from_bytes(anchor_bytes).unwrap(), + ); + + for _ in 0..num_recipients { + builder + .add_recipient(None, recipient, NoteValue::from_raw(note_value), None) + .unwrap(); + } + + let bundle: Bundle<_, i64> = builder.build(rng).unwrap(); + + let bundle = bundle + .create_proof(&proving_key) + .unwrap() + .apply_signatures(rng, [0; 32], &[]) + .unwrap(); + + zebra_chain::orchard::ShieldedData { + flags, + value_balance: note_value.try_into().unwrap(), + shared_anchor: anchor_bytes.try_into().unwrap(), + proof: zebra_chain::primitives::Halo2Proof( + bundle.authorization().proof().as_ref().into(), + ), + actions: bundle + .actions() + .iter() + .map(|a| { + let action = zebra_chain::orchard::Action { + cv: a.cv_net().to_bytes().try_into().unwrap(), + nullifier: a.nullifier().to_bytes().try_into().unwrap(), + rk: <[u8; 32]>::from(a.rk()).try_into().unwrap(), + cm_x: pallas::Base::from_bytes(&a.cmx().into()).unwrap(), + ephemeral_key: a.encrypted_note().epk_bytes.try_into().unwrap(), + enc_ciphertext: a.encrypted_note().enc_ciphertext.into(), + out_ciphertext: a.encrypted_note().out_ciphertext.into(), + }; + zebra_chain::orchard::shielded_data::AuthorizedAction { + action, + spend_auth_sig: <[u8; 64]>::from(a.authorization()).into(), + } + }) + .collect::>() + .try_into() + .unwrap(), + binding_sig: <[u8; 64]>::from(bundle.authorization().binding_signature()) + .try_into() + .unwrap(), + } + }) + .collect(); + + for sd in shielded_data { + println!( + "{}", + hex::encode(sd.clone().zcash_serialize_to_vec().unwrap()) + ); + } +} + +async fn verify_orchard_halo2_proofs( + verifier: &mut V, + shielded_data: Vec, +) -> Result<(), V::Error> +where + V: tower::Service, + >::Error: From + std::fmt::Debug, +{ + let mut async_checks = FuturesUnordered::new(); + + for sd in shielded_data { + tracing::trace!(?sd); + + let rsp = verifier.ready().await?.call(Item::from(sd)); + + async_checks.push(rsp); + } + + while let Some(result) = async_checks.next().await { + tracing::trace!(?result); + result?; + } + + Ok(()) +} + +#[tokio::test] +async fn verify_generated_halo2_proofs() { + zebra_test::init(); + + // These test vectors are generated by `generate_text_vectors()` function. + let shielded_data = zebra_test::vectors::ORCHARD_SHIELDED_DATA + .clone() + .iter() + .map(|bytes| { + let maybe_shielded_data: Option = bytes + .zcash_deserialize_into() + .expect("a valid orchard::ShieldedData instance"); + maybe_shielded_data.unwrap() + }) + .collect(); + + // Use separate verifier so shared batch tasks aren't killed when the test ends (#2390) + let mut verifier = Fallback::new( + Batch::new( + Verifier::new(&VERIFYING_KEY), + crate::primitives::MAX_BATCH_SIZE, + crate::primitives::MAX_BATCH_LATENCY, + ), + tower::service_fn( + (|item: Item| ready(item.verify_single(&VERIFYING_KEY).map_err(Halo2Error::from))) + as fn(_) -> _, + ), + ); + + // This should fail if any of the proofs fail to validate. + assert!(verify_orchard_halo2_proofs(&mut verifier, shielded_data) + .await + .is_ok()); +} + +async fn verify_invalid_orchard_halo2_proofs( + verifier: &mut V, + shielded_data: Vec, +) -> Result<(), V::Error> +where + V: tower::Service, + >::Error: From + std::fmt::Debug, +{ + let mut async_checks = FuturesUnordered::new(); + + for sd in shielded_data { + let mut sd = sd.clone(); + + sd.flags.remove(zebra_chain::orchard::Flags::ENABLE_SPENDS); + sd.flags.remove(zebra_chain::orchard::Flags::ENABLE_OUTPUTS); + + tracing::trace!(?sd); + + let rsp = verifier.ready().await?.call(Item::from(sd)); + + async_checks.push(rsp); + } + + while let Some(result) = async_checks.next().await { + tracing::trace!(?result); + result?; + } + + Ok(()) +} + +#[tokio::test] +async fn correctly_err_on_invalid_halo2_proofs() { + zebra_test::init(); + + // These test vectors are generated by `generate_text_vectors()` function. + let shielded_data = zebra_test::vectors::ORCHARD_SHIELDED_DATA + .clone() + .iter() + .map(|bytes| { + let maybe_shielded_data: Option = bytes + .zcash_deserialize_into() + .expect("a valid orchard::ShieldedData instance"); + maybe_shielded_data.unwrap() + }) + .collect(); + + // Use separate verifier so shared batch tasks aren't killed when the test ends (#2390) + let mut verifier = Fallback::new( + Batch::new( + Verifier::new(&VERIFYING_KEY), + crate::primitives::MAX_BATCH_SIZE, + crate::primitives::MAX_BATCH_LATENCY, + ), + tower::service_fn( + (|item: Item| ready(item.verify_single(&VERIFYING_KEY).map_err(Halo2Error::from))) + as fn(_) -> _, + ), + ); + + // This should fail if any of the proofs fail to validate. + assert!( + verify_invalid_orchard_halo2_proofs(&mut verifier, shielded_data) + .await + .is_err() + ); +} diff --git a/zebra-consensus/src/primitives/halo2/tests/vectors.rs b/zebra-consensus/src/primitives/halo2/tests/vectors.rs new file mode 100644 index 00000000000..a31aa8197ea --- /dev/null +++ b/zebra-consensus/src/primitives/halo2/tests/vectors.rs @@ -0,0 +1,5 @@ +//! Test vectors for ingesting and verifying Halo2 proofs from zebra-chain::orchard::ShieldedData + +mod orchard_shielded_data; + +pub use orchard_shielded_data::ORCHARD_SHIELDED_DATA; diff --git a/zebra-consensus/src/transaction/tests.rs b/zebra-consensus/src/transaction/tests.rs index 3f5c7140d53..08a001aed3c 100644 --- a/zebra-consensus/src/transaction/tests.rs +++ b/zebra-consensus/src/transaction/tests.rs @@ -1,4 +1,8 @@ -use std::{collections::HashMap, convert::TryFrom, convert::TryInto, sync::Arc}; +use std::{ + collections::HashMap, + convert::{TryFrom, TryInto}, + sync::Arc, +}; use halo2::{arithmetic::FieldExt, pasta::pallas}; use tower::{service_fn, ServiceExt}; @@ -6,7 +10,7 @@ use tower::{service_fn, ServiceExt}; use zebra_chain::{ amount::{Amount, NonNegative}, block::{self, Block, Height}, - orchard::{self, AuthorizedAction, EncryptedNote, WrappedNoteKey}, + orchard::AuthorizedAction, parameters::{Network, NetworkUpgrade}, primitives::{ed25519, x25519, Groth16Proof}, sapling, @@ -93,7 +97,7 @@ fn fake_v5_transaction_with_orchard_actions_has_inputs_and_outputs() { // If we add ENABLE_SPENDS flag it will pass the inputs check but fails with the outputs // TODO: Avoid new calls to `insert_fake_orchard_shielded_data` for each check #2409. let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_SPENDS; assert_eq!( check::has_inputs_and_outputs(&transaction), @@ -102,7 +106,7 @@ fn fake_v5_transaction_with_orchard_actions_has_inputs_and_outputs() { // If we add ENABLE_OUTPUTS flag it will pass the outputs check but fails with the inputs let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_OUTPUTS; assert_eq!( check::has_inputs_and_outputs(&transaction), @@ -111,7 +115,8 @@ fn fake_v5_transaction_with_orchard_actions_has_inputs_and_outputs() { // Finally make it valid by adding both required flags let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS | orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = + zebra_chain::orchard::Flags::ENABLE_SPENDS | zebra_chain::orchard::Flags::ENABLE_OUTPUTS; assert!(check::has_inputs_and_outputs(&transaction).is_ok()); } @@ -145,17 +150,18 @@ fn fake_v5_transaction_with_orchard_actions_has_flags() { // If we add ENABLE_SPENDS flag it will pass. let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_SPENDS; assert!(check::has_enough_orchard_flags(&transaction).is_ok()); // If we add ENABLE_OUTPUTS flag instead, it will pass. let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_OUTPUTS; assert!(check::has_enough_orchard_flags(&transaction).is_ok()); // If we add BOTH ENABLE_SPENDS and ENABLE_OUTPUTS flags it will pass. let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS | orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = + zebra_chain::orchard::Flags::ENABLE_SPENDS | zebra_chain::orchard::Flags::ENABLE_OUTPUTS; assert!(check::has_enough_orchard_flags(&transaction).is_ok()); } @@ -231,7 +237,7 @@ fn v5_coinbase_transaction_with_enable_spends_flag_fails_validation() { let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_SPENDS; assert_eq!( check::coinbase_tx_no_prevout_joinsplit_spend(&transaction), @@ -1251,7 +1257,8 @@ fn v5_with_duplicate_orchard_action() { let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); // Enable spends - shielded_data.flags = orchard::Flags::ENABLE_SPENDS | orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_SPENDS + | zebra_chain::orchard::Flags::ENABLE_OUTPUTS; // Duplicate the first action let duplicate_action = shielded_data.actions.first().clone(); @@ -1617,9 +1624,9 @@ fn coinbase_outputs_are_decryptable_for_historical_blocks_for_network( /// Given an Orchard action as a base, fill fields related to note encryption /// from the given test vector and returned the modified action. fn fill_action_with_note_encryption_test_vector( - action: &orchard::Action, + action: &zebra_chain::orchard::Action, v: &zebra_test::vectors::TestVector, -) -> orchard::Action { +) -> zebra_chain::orchard::Action { let mut action = action.clone(); action.cv = v.cv_net.try_into().expect("test vector must be valid"); action.cm_x = pallas::Base::from_bytes(&v.cmx).unwrap(); @@ -1628,8 +1635,8 @@ fn fill_action_with_note_encryption_test_vector( .ephemeral_key .try_into() .expect("test vector must be valid"); - action.out_ciphertext = WrappedNoteKey(v.c_out); - action.enc_ciphertext = EncryptedNote(v.c_enc); + action.out_ciphertext = v.c_out.into(); + action.enc_ciphertext = v.c_enc.into(); action } @@ -1654,7 +1661,8 @@ fn coinbase_outputs_are_decryptable_for_fake_v5_blocks() { .expect("At least one fake V5 transaction with no inputs and no outputs"); let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS | orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_SPENDS + | zebra_chain::orchard::Flags::ENABLE_OUTPUTS; let action = fill_action_with_note_encryption_test_vector(&shielded_data.actions[0].action, v); @@ -1695,7 +1703,8 @@ fn shielded_outputs_are_not_decryptable_for_fake_v5_blocks() { .expect("At least one fake V5 transaction with no inputs and no outputs"); let shielded_data = insert_fake_orchard_shielded_data(&mut transaction); - shielded_data.flags = orchard::Flags::ENABLE_SPENDS | orchard::Flags::ENABLE_OUTPUTS; + shielded_data.flags = zebra_chain::orchard::Flags::ENABLE_SPENDS + | zebra_chain::orchard::Flags::ENABLE_OUTPUTS; let action = fill_action_with_note_encryption_test_vector(&shielded_data.actions[0].action, v); diff --git a/zebra-test/src/vectors.rs b/zebra-test/src/vectors.rs index 8e10d4e806c..3b6d66c5803 100644 --- a/zebra-test/src/vectors.rs +++ b/zebra-test/src/vectors.rs @@ -5,9 +5,11 @@ use lazy_static::lazy_static; mod block; mod orchard_note_encryption; +mod orchard_shielded_data; pub use block::*; pub use orchard_note_encryption::*; +pub use orchard_shielded_data::*; /// A testnet transaction test vector /// diff --git a/zebra-test/src/vectors/orchard-shielded-data-1.txt b/zebra-test/src/vectors/orchard-shielded-data-1.txt new file mode 100644 index 00000000000..f4da6b921c4 --- /dev/null +++ b/zebra-test/src/vectors/orchard-shielded-data-1.txt @@ -0,0 +1 @@ +0230e2b520fae19071aec3ead6e7b9b7b70e8cd50bed24d3cda4c0fd2a7d49e69482e4d223b7c51da15565bf7370bdca547ad282c502851b3d1200ea73a26bb50611628f1407b4145a6cd6679889e381bb7a234988e5b87a1e3d887c09238e3abfcd679124bf1913652e122cbcbb3f1f4df063a0f4fc51255d6aeb7823db590317ac3a1225bbafc1953729e388f5862990c475cc6ddfb7b121846002b3fd8ac92a847c4b47460475497009733c37262149dc485a257ce817fe8e86739bab3ff9c14dc26e40aa975000f24e3466327d85ff90abf24d8941b43b574e553a076b7ec204f5591d31087f38c317f6c376a1b75bb8360f3f3952c59ca5fa5f1faa3e04b5e51a0dc348745a91ac6ce18675c20d5ce9dce15568519729e5e1f2d51e88fa85ab5a91f73ef14d80898b0915f1dcb3482c6a1fa11526cb466eb751374635b8a63d1e1d5b606af0f5741850b7818ea35cec06bcf662f322ff97aca470b99af15ef3a262ab692f7e8a0c9cccb9de21082aeb8d563408719210cc8adfca4f245059b8f61e07ec43c09c396d733511bb5dab2ed9d0a8119aa8377f56b98eef07be3acd686b85daec8401a088d5561b132ba5e63bbd0932e0c3dd9067bf26888350e58d45570d5790016957e9f22c262285fcb250d33e351a56e5070ecae86f121a3a6510b5dbf5a798a8b1e3460657919d95db31c87c131c38f1cf6db3be0288fd2dbc1019d76a3cd429570fa5135350618adc2560279b8c92a9a699b2d098063aa0184507ef9adf1dde8d022e089bc633f830cffa03d10255f8dd6f90d1efc08d409a4e565bf1122db8a374cd20145fe7308d6cb44dc74c453930ec1f58db63b53a3ec9eb13b3060548502f7b2314bca5d9dc435574f4d30dd5fd99b017f78e365d008d1e1a7463e1ea6a21f0df13d6f662dca295c78652a46d21c3e90de3591a19d35911c09f869470bd93758f1a11c06785a7d9636817731c0b66c583f89c140ec5eaf5f3c629debc89be6ea953056d3c4cdcd4bf860c0c130e3227d17908550158411d530f0610f96aa8d8b94e448de2d354804acd56a81da7f2077a003f78ed017f876b37d6ef00a25c0810a72a40e8c4408b796b7be1c35d420837a28cd8a9fc648e9ec239cb0889ceaae896fdb7ffefad3a85547bb9100bcba5772e080c9f7f4f4f19f6dcaad9b2656bd599fc2c07495b2090ec59ed926bd9c0319f0b10d79668d4b7bc13a35ef2dd50799b67670c47d03b335c65f46abc356dad1bd9ae1707557bf57e8253f657464991a35d245000f16722d4a189ac52b11c466530aa33e6e18d6143f0b62dc7ab1ac8402fd36e660abf1b9116fa5ff18f99fff0d829579fb2ce309217402747192a6ebdfcc9af6ddfd70eed1fb5e5d4d6904099864ea0dd1e4ffc314dfd39eb40cd2407c6aa3cc2f74b13ca4e734ed05f76fb3233f5d8f932b816f9404c614e195a91d1e5055f588a09f81754b150b17f406d9d6e8525b5c4b805ca465e3cbe70204661f0944af9bb73a19a012ef4c2e05ae04ed0a6a3f7da5ae96b7d35de7948d291e1c970a9b80c20f97eec3b29a068df7c68f74b8d50ff67a9a6cfecc5f31fa514410c9993f920239fc62dd4b47975e32701ab4b5e5b9c7fae55561e838d15b10ae069dfe2a647df3367733a2976701d432416cd6ec2c0e401daea3d9c8396739349aa911750017efd4fb07440df2d8fb21ee9ac5443cc4e2c135aa2929dc79b0bc36a54a7344e6a988c2c12d0675efd6fa0fb35eb5b216d9a2c5d6767d750a4a671678ede585aadcfb1b51b1ebafe5f14c134929cb33c30049dbf42e89ad03d51e4648af6e033871cf218834b116a413f018ad4277e45aac1f22295ef9e08f528b0c125fa97e1953302af8c05d2a39df4050c2972c24c2ce79c115e9e2341aef96b4bfcc807ff765bb8bea4ac7eab408f5a656e46c3e32cb381661846fb3126218806690686d62b698e96f96b135e87ed1f547ed87e94e1f43d2651300b48d73c1b1f7460bd63ebe7b08dc8582d2cb42c0b9b44b3cc9a17832afc60192f776e2aa206eee77594bcabfb64c94001d70919fe6d7d52d5a4234c243df7e109c401c82184802822a527bd7077e128358e7faff7626e588af7b4a1a22999854fdb6d55646647849e554f1534770ae519ad2cb42eee07eb26a0efcda39fa332d720853b7b41840838518da526f89d35b4c1e067df01f32999228c513e4c0f21cb96268e4e30144bb0f3d7c3d0e0faad2665b2ab57cebede00f1fec4a7064be121972cf99c9a0869d40075b39281137c95862736f1ee9c89f87d7c46228a5ae7030a000000000000000000000000000000000000000000000000000000000000000000000000000000fd601c04c2e3be07d4601c6190a5838b79fecb03a7e7fde949eb2909d20fc3e6401f013270eb6134cb28eaf93cee375e3a5b887c5abc00a4913957b76df853e2ee05a9352b37c6b87ce27aaaa4cbd1451e101c00bc2cbd7f142ed8ed8d41384091970cc6ec7d6fc6c4833b9bd377ca2bd2f164d267b1980a7db4b45a8d97d0bff84b3a28632356abd199ff94b2f7b9bb2084ecf3b164e8bc568aff111a4e99b6b195bea377366f1e677a8648954657249dd4f7363901f3d55b4354e34d64dcb4587aa18c1721ea9cde5386b7df7c72567146acef8a33688a05fa8ac0b115f17f3811bb204a9fee7036a9f84e55e2bd84fbbe8e7e255d62fbd8874c61101cd4ede0e316a082f225be37267c5fe1a5dd287bb987b632c47c788c4e837db1f042a07c6918e4c9aee1d294007d7de571384edccc9c0628f326d0bde4529b05177dcd9ea626261a1cf3143b51a78c2c93087e01e708a30253a38ab9b1a0fb05dccb0281a02cee6f279c1344d24ecc5812e08fbd91066fea96db229a1b7bfc60d7dc2494fbbe809f35d81f8d1d56bbdd0786e186d831e4ee6978d8958739772071db8c867011e8f18baaaf1489bab2263faa0a6d76823169ee01ac210395672aee186efa8d111e22d981cd399cd993b1e4230be2ed30752781c94625c81cbb51e1f4aff1c93ae200bcf791905962ec1a6a3e78c3a0dff6b90d3866fb04ea254819c00f27511bbda9382ed30d908b939c1dc91f89ecf4aa298ef07b4d1286aee88d84c5c6d518ec35e4e704afd96bfb0aab2add9fe3197ddb074208926f9a8d284a9090edf99d92afa8a272f36a72d5bfb78e72cf5d8176f0a12dc1b8978a61686977e3a397b479ce7d6ae480aff655a7544f17360001a680947d3756e22c499455d31bbc769215954fe6b3a8ac73ffbbceef80b24f8968454497d667941d80f95428e06b40142b6ef172b2ed72b7f14f427c192caf81bb3a61ee4d1c5b2859c75a8b318b089eab302a80a13631d4e07baf96dfbbc91eaaa16e1183883d9843f2b740bcaf6584bf1173b30715a2db3eb90c4d5d67466639dbd14b7203ad23e6147fd24a4d352a87608da266619037e9f840b3df3578b19e3e3b6f275bbb9fa297880ed9ad34146b98e2a0d0d7cacc384bd2d1d9d98efb05039e93c9adc82405cfb1f2c8b40a148c0615de7437a481976001a6b480faa15ace0f7552e56ede0c9948ed07a27792c1ae127f5fe4f9297ad056bc175a4b1e30c5d2779496d3d67d34482c160ffd2cb376a3e5e92a4f97f7b973ae52e58d730aac0098bb38f8c5aa096ab738cb3488e182560ca3af4949d8746926e8d8b90fce8c1ca46eda9b77aa924ff7b7f76c2bf00b336f73a00e5b7aabb30f21b9e18105d60135b4bb8de7c9fc98fb0e1b9f9878ce6e2efdbbf37b4cf9ff5b71efd85041f17adcbb7fad7c630e70a7a5b5650b3e511b780ba1e254d6609777382eb9b7edfd46677d4fe4e4d0fcd9da8abf9821080c7dedc10be9c6f26c90c5e86193382c4a61db66d973bd433251c3f6a41c34eb1e39647dc4e512e1e9cfc4a1db921757dabbd854da5d882eb4036c94aa948723e7aea234052a7730a1d59ffba8a389d8280b55cf14ebd5e49707c2f533109840e9da2ee2d782115675a78a77f349fd6bada80ca8e76cee2708d3f9f091822813825a0c8fc7d56e1046e7bf7d185e1aa0e2e30dbe540017ef75aab226bfa1b7d2aeaefd513b4fb33e693edf71ddcef4a5b136e1dfe3f7d8c1ee83258234770b08e6c56ba18f4eba0e4e780ce5278a5c565760c69182e29cedc0d57c67e7012b9b8c2a78e4cb647955167c47c4e0a34fef0426037a33c12c43104c6c164f0d2c6b909ce78cc93b0016b9638e86899d9bb14faaba66017f9d2137913fc453248cbdb09b76cea1d6ee493ce4dedd501db76a83cfad6e9ea92f40fcaa9f536a0a900a5d8e03592a1827a542c763f01c932293c0a35418340a65edd2e295419100144ba832aa94dc9bb5fd8e383ebd48def1f01a3eea82bd7c146617ff6bfd7645307deb206a031f39bb188ebd52a781dae3b86ead58782d2f6cd3bc8bf38b480f9f377e33f5905294e135dedfe542708a573c9cbfa53573f9ed973db68381ab9793fd9f6c145b09e191cd34ffa293fff75cf977376aa3a441d75a80fa70f6d5852b2fa8a7fe131b48ac8d5c6030760d16e6bb5be4fed549391730b7fceadee9babb298ff28cf5fad5ea002da349d3d3bec0437e5bb4b155e7a015a6fe2560199f371ad8e6ce2906dfae0d0fe2ed4a92d3efcf415a1eac560e974634048349a1c617500b621635b9d19e20afa8cd6d44485116ab2089457b40003e04832c9ffb093d5c6757d818487c0f178cfc6ef9b89b9f849b0d517f693cc9e0a5b58a3f1cd7bda5034c0da55cad0aca94b92ae0447b9a79fc40255fd9944d944304264d6a680b3c2e435b77c0cc7e5cc593e87f8750081d3c93ee0b5dd214023150a9c77370252a31b0d3de9de37b2a2b0d750c49594cea407ea75ed50f84f2da4c82a4820a270644079a0c8a5adbe052253597720e6e7d48877c060aa666bd8fe30239445f34c3c22f31005ffc04c9308707729d35ed9fe4c9f78360e4802fe817da060fea1658145a098e1b8e4a0eb59a6455af36eaadb1281f832369cf2a39f8e307483f1ab5dd82ff207443d69dd69d999b583d71b03926da756443866033fc1aa1c94d206fab1f4fd0f2a2ad8f55522aa9d3bddc8b7cb0dd69d203c8ea9bc6f4e4cfef0f2514c25e3ae05cae5bcd72cd55a08dab6af19319a2e174620001a098eb476602ebfafd03890d647dd5d5be8f3a6594f6da402de9d6621b064c510997eea82529d435688bc64fcbebba9416e456c0dccde21e555b4492cea7e29ce1111a01a50d19f1fdbd03c665742d01f5e76c974f05ab8940305b4c88dd215045a29a067720ce1638773d06c6be07c3272be9d73c6c55d47e5b72da704ab70ecf1bc58b6131fdaff7e2e8d3cc4f4153d116e8177c3ac5d9ff55a492d162c3107a237ecb9b262f312a868dade348a1401c302be149c2f3449179932f8d4c3658c75858755826dfe4845d0b7b3fbfd830b6e601eb77521021811d2508a2ad5eb9d410c5405b33015f0a51cab6064b14f94b6b79e414393ab43aad30dffb41524e45b3a5679a189e3606b0d2fd9c1ded19e994e59ca0bbe47fbda44412ad50ba3ff482bc8fc8183e9a85375f2e600903a26f43d218503027e802f9882e7c9abc51efc37f2b3e1c7da957c88fb14d3e3f58075d230c3d242f8e1bc9827818b96ddd00013a795b35d65e6c1ac860e171a28f972db3a14d4a071c93c80b3ff43dba2db8fb85d0401a9ba990e19bb8e7cfe8bb3a0303bdb64efffc5cb0f05053fd57544f9bcf14df1152a23cc59fce55c8dae060c90a622db06a31056ba8472e4e75ad0c9f167a51248857c781c85f0123fa5fc5a74c5bf2cc9599ac2ad49c4afd11a3dcce20c3ec3563be6e798f2079cebc7fa98e9993d9aae8d01d7d59daf554afc249370a875e28e18374db40fade3e279eb606cacc28cad3a2a706792853414e6a41a010c2ad048aa8ce14f62291b7c8fbddee1bbcec1a87eb81aba6516d3c3ca9df5102cef615257576793244d4f98ca14015468b1d7ee7063b7b8cc30a691880fdb54b5e7902dea2f506533e6bb26d0161ad50a05603623185a75921c099f9f08fd5c7f36d315f0103a5110f36c424760e32f83cbd78f850ff0f7d610f176ac654705070882edb8ea2ecb56ba53eb26c1eacd92c79e321bf7c2ccecc1213d231562d256da73d70f513c93d3baabe4eb6415aa6c1ed0dba0e6369ea20f61feaf47703309ba424a6aeab097a77eeef17180bb9e2318e88007762637b184d978bf1c7edd0595a27e79b109c70baaf89f55e085e68fd35f037414a23853b83bea2adfb8420f33c16915208e423ac08c81c8b5a709c2671a63af0b4e6d8eb90c6b9dc11ae4b4a4d13b3f0da46956f999d9ccfba6cf963183c45d9d31c85b28d77b4daf09165df0133fa2742d86896b058910330d09a033e2be632930b2397f4af88de9c10b10543360a717d7cc09c277ab8aeea9894a9dda9d460e805bed7fca4e260ac9c8e9d603c305d95e9c8f85377cbc64d4822f070dae0528c2b5b8cb5d3cc97190fb840d503b07853964e1687334986796659b28aa0286ed88c986e04418f355dedf112a1316d606de4a17dddb63f85c9dacbfc81f905f4ff6f997d4a0d1939986e16ffec3d2f6acb9d081570b4564b511940f655ec6553bf8f12a35e7ac080be502665882b90cdbe9e5d9225c9d087d3f8dd40d0204bd93856ce987961b3b661c79d070a398332abfc07ed8f09fd2a7bfb7cc02f40a2903f78be46442d9e225160615b773b1724fce894e7d0e63a1cc40642f79a8813d8d56c3fb3cefe801da1b6439d9b0199626fd878c65a0e298a43b28d3f2989e2e59a5cb1102fc643f2964196ef371f2abdf0ac206dac8d1e3d53b3284ba4e9920f96eba6d74775843ea7d2a668b42ddb4c56aad0c599f98b6c937163f7423c88a55d2b376b425d3597145ba2d6e22b17f2073bbb08096ad0318eaa25bede67da088cec9653c857544b1a287bdfe932f296433df2cd6281039f78ba1f4b7032df98f2656019153ac77edf47d270a1389ddc414590423b0003c23ce27cce628c9b73b37f2dc8b7f24ea335b9877623035df2817906026e376653346502b3176a763583fb0bf96c325a3dda14cd2b5b1bfc67aecf047b721d8615b107713bd3fef642a8503351f5904b4706791e2283373951a2025859773a15715345efaae8d26c5467ccfdbeec9b4e7f9e9f63c0913fa766d0df8f311c9263dfce90b5562f3f1467970c10a2304a97580ccc31a44724043eb2c49ce1621664bf8dd14f969616f8970da1d9ab002798756bc3b8e71a16dbb28f77ab80776a759383274ac85a3e6d44676229c4471a947d97754916eb0b99f4fd8ea46062565095bf24c7c8376fa9ac53bde17e0e33d343bad15fa349179f2f162744ac3fd38b7123f754420731877271effd931efb0413b522d9adf303a88fa0ed6128bfd09caad70e4680b1fe99a4fdc6614bf220c19b4fa6c354880f5582d28d887222f8a1a4d7425fe53b022d31fe46c237b5b31f25a6ade9cd6e02f83a947f44c28ad4cee9b37597cfcee2d4917b9442a7201ed735934423a62a2d14eb8c2ae2dac6f0400fc3bb094cf8a31da5030d92efffc799a4e31c8ed6c91c91e7bd40ae31c8a665e68db45b6996f74c1e978204a40460bf4725fd0da434343ffd509e0acaa9195237204c7b06586291e5b92751558e05d3e4f1061c68792df97f33a684c634ccc651c290f65f89da0f60ae301c753376d15252992374820e8d8bdd4058277ec9b8414d15a7139b7569a15804480326480f9ca0a32e60d732291c6d8363e3e447145877b6a3bbe475e7440c5cb67fb4ef2879f5f0e660a3353821f6c562608e25d6727053502e79ea4c89de39a2e278b67bb0a0c0bf2da12c78af7ef28326ead14156262fefbb1ed9bfd276a8c5355f1bfa2717d78229a63c321c9a4b452c7186847d9d67f07473a68da2885627218dcbcf86300c64df5429b52f929e0776c95ea59e53b3e4b5d04f26d2c42db56b4cbb3ea431185cdd6502385972c7e9853779db75ed53cb2cf4ba9f6ef24a44bbc119ebc0f148bd006024e92c6a8d6c7aef4965447f981f60a64b0902bed587d5e8476605fdf10f8bf82c3e5f524ab2a124b5ea48a9d3ea0727b38a983756b843de154c0cbb5a9630940865415b7070f3c646387d5d980fb044a54f8031757ef5368b8f5540ebb444a0148ff3c005e388188469bee9fcc78ddfeda8913f6d81931c3b662a98e6843bee368a79b33c0f3c00851e326a3c3d23c5f4d5c0830ccfb989d9f3e6c513a7291d2f31ea4e046a6fa81b145eaf0f7ba79c09de6f508ff74aa5ed4d4d917c98295a19c557eb32da85fbb30914943b93e418da1009cc4f9705120e3df4e9e8c89da51f814a3bbe2f9221bc300482fa7ff6d1927384c1eb419f059feb0d4163325b3331fa032764c31d2f50112e6e2aa4acaa6035fdf3128c625ea468ce2549ad94691512d239bdaf37838bc54a1c10d79eaef07c8906d7117c82d8a94ecb96a3095723e9f2db243a5fb5a6463d501ecba763d514bcaeb1466775305fa626008efa252b54e28d7ceb84613abdf34a88b8639c4f5bf5e38af528a97797884204e036e7205b1e6d0b719e3b983cb15d981e5bb8c280f477fa17695090dbd54b22518065219169b4c0e1e379e9ebb9ce75cb9616a115466476e9717d63c9c2827afc3dcd0b10795708ab5cbe29cac7d53ea381e859d9a0634b9c2455e368e8c7d43443f221b9d2f2682508cf62e9817c25843b7ea33a01ae2affdd2b2dd868ef02445deb10c60c69cb96310ffd293d0f163f1e7d333e9611aa0cafa1b02e035201dff1761cb8f2673fb462a39ac1435fded4a2574e8f3ab1755011add0961bcbed871c7a354686912bd5e2f6a2ec65422db6066e6e2404f61eff01032e3d1d3e7ec5e7a11fee930bdf2d8823bb421781431dd8581552d81d3a5f3083b3e9fe0df7f08b6e1b91e7ce0839e84c3ee0fa9002cf23b0d9c21c101d203135dffab6e062c7bf2a23764119d583ced3a8b1be79555422b892db431ddb0baf3e751c7bb9354bba2937aa4e7bde233ba5b438b47b3f4d087aa338f47c7d217a6175558bdb7d1c8ce31ee79aaa48f8499b8f91a1f1fac1e219f49115f63bbb9181c2d24c256d5e6fa22f568fb4384e2d14d3c18f572a3efc8aad4f09cf6d15353410ea2a5c0adb882f37efed76fbce709302d30ae3778ee609f07e4bd9b1fbd30d1409e0e5e2391ac4236393c475108518709f2902edbe4103325c0d046d6df4e36730cf023bd280bd2329e70cda2e4b47f03aca265da07882562dccb2beba14216cd45a27da8fd8741746e7d05221e90598fd524e385e0eb6aebaafb121a5f4584cb23cdc2cd9dc643f889505a2b061cf6cdfb46e177c276e9d0c1484ec2313c4ea9eb1e875bbb832122d6f5c41457417add6e888b7a7c972e5ccf1760797ef37fb64f7300de0bc2b24f1ae287f8c80694a68a06523a5bd649cc3c8da8a1f292b5b80d63eb3c87ad72da14ee5db60b866d02893c8a594bb26f90c1d850375578f9cb259823617556118409264f951b6d9b0aa55be54c029739061cedb14e33e85b29f94df2c4bd27718a92b7af1e85875e745d27687785e113f0a7c5bf56bc302dc5f4a4b28806805264e96379485703516c9cc279f3b7b463927b54947410e78cc895be26a30f3173c8c6d3699daca0203f39879f1cd0d985c8ea7822724d25aec0bb7bb20d1dfcb3bfd0f62268af41f50ce19b9667126978b8da29756c27f427f9bde230cf244dc36f2baf54df441d5a046885d64758a013ed2ddb1234727bb7357e49b5850f8610f53e003d3f3b508d7d1eba15a5ff1a9aaf317ab7ac071315b7b22e6a3b7013439fa5d5fb1a927cd82dad0dbd7d1e64a1eb59b0bb937f9b58ff000b5cdcc20433b6b30ce6133b73d28a47d2d5e3b1ce5a1ce851940b2537766873241462ea1041e286495d7a2df3f928ac022631a9119b54d8919ff37f8d3cde9ac4a517b0be125d5c74181ce7610cde02797b15408cadc9ca8e32bacdf994ecab597572d71550cf37d7d511e021d72ad433bd586c6d12c183d37eae8abae4e2e72a2930e138e2d9e8cb7d4bd73b97c2cdf3a2d0b408fb5e6400e2385cc54c3de8c9c61a77a0301f8058482aaefd83f57a2519bf1c87f3af9d164d783a843528c5fad1f9435112e9a75f6db3ddf57a5e5082d8398ec9db6fcd2a3ba450e0060eadcb80f96dd8a178817c155794ae13cf4897d71d0526ddb66f4b0a6c72287a96de1570844f02d005de76147dc2e56cd202b672f3ba377ee1e515250ab6ad49f7654a1cf5c392913358e4161bcb9dcff81efb335094eaa9988bef989c4bf130eba8285a9c51fcf026b7bebbf00b3a03ca4e3c621c589c14c45a2d61e15f945edbe68cf89cae99d1b72cfd726f3bdc46e16b2fbccde56240f91c7d76d618af9a1fbb6cdc8df4a3e360b8d74304cda52e951c9cb9f702624e5c652405f44348c7a32bd803af8ce653fcc0afb5b3762d165bd3d620af072e52e03ef6c301601ace184c59d65235cdc27c0dbb9f8f866f3f43733057053c8871911a8121df000d92f4c3724cacf8f792f8aa36aa0f89a0588a43d9e11ebfbd3c803c31af3a038f87d5b2dcdf5c77b3a13fed3d840237392aeb4f45c2029763c486fabe7b0c8ad3d7e8329cf4002784822fe07f4efb207b2768419937f2ed869c37e45912d6ee5ebc81740f3039f089e14c9e766864f3767540485792a3f5d79af37cafec254d674a0b9d6ed55e1883f3ff42e02b269a20af2125fa607c2c6dd27fa5055d4a717b04679395967a57b853bd194760a677e7148ada06561b741f45f1ac4eeda19cc5e81e5c8aabf55207b163410c4ee03f8a4dfb8f4a681f62b848c62f58cfba923f5da0cfffe95c05ee0390d07e5642cc7dcb92d195cac95fc776071745e6fda35dc5a3567d13e55196836dfa5878361e43085a047d0ad3e63b04a74a4830d574aee6ebcbc18cb7709360e9a0e769c6181ba7bb50dbcc095dc8f2747c1912471fa19d6e984ba996bc9e7359d385c298e7fab94a6a3eab791a806dfacc2e6cc1b1eaaa72f6a00dbad08943c13045b543403bb4085c6c9ce6daeff5e44abb254edc8fbdfd374bcd9c363d1101b3cb72240684b4d8011143ba97a7152c74f79249774e6e225aa958b490e462309a2c92aac2c5ef5f86a8bb8fb2ba82541b615f8d2ca0328cf669fe835366608e601e2fab2dabde1aa5a9c8cce099899f494f198bc88af927a1fa694f2162501903ad6deaf14f68c477c94991311d11de1a4332cc25f7b3723423c21a3f6c806d2ccb202d327b7bd8dc45d734ed3023b0a8f4ea5e9b28afe41fa50ccbd0a8b1ed3d50364cf155e529c1e36cefd47429f5a2a59f27f7c652a7e14b09bcef6d92dc601e9cdd41f0edea0dc49cd69e9ee15d068715df69c5f66c0341f82394b9d117223ba20dfbd68cfccc37eae1a9457e11ae3423e14c410ad0a92728ab42e161340b826c978c08ff65ae2eccb850516c9b598528bf5ee644e34c482c2a9c8cd9bb86ad5c9bea3b11b46e2b9867d1c8e04c50b82eb1713038b3de16afea3807009465654b662420aee3e3128c1cd076edfaf561dfa834f0e75be0fc764acb9af37c371183af576c6b1060d3e2ccb008441ed0fceaa0477138e99af3593a224c9aa313e45a50af5aceb4d769b96b18cbf44489d1eee90f20d514136b6066b70739c288638eb4cfcc8e7159deb7e14b0b3236b120b0fe3bca04578565e4338f0d80a162ea2a0c2a3e6a696c6052078c93c9d0dce17f59f1840ad44609a729595a4253bb7c659ccfa1bcfe5dc3f01d746da295fb1b98e175de9d042debd7c21f03137000f2b3e3d242752b469d7ab806fd9a5cb053e5339abab7ebbbc271bf493213d656689ec3023e6d358e4111615514729c10eb4c8b47e00bf1767f7480ae04c85b3172fabc96aa9610a9cc8566a748d42c3ef3f7413c8fbd73dc34e56ecb614234262a3f6c90abcc1d87ac27c165caa7bdcf1684559faa294f3f6be3bc03c00004df1075306e047dd831bbc775321adb1bb73bd23b5477ac4b77345ac1cee3e176a3ef4a4b072287ed5d994e0e2f7e991981ec9e93f87501c548a0d96d1921d81d2fcc7a4432cbeceb1613fa1307f6d206792789d8614c8641e93a6016eeb6e3658ea1c791edebbb7a9f6d68570d089e63358601db9e4d59174a4273597b6cc1821e577cb9892aa64de796e12344fc965642fda2e11a6bec55ce6428dc967dc8db3101ef439131c92771e6388521ea4627cba5c49a86d87d1e268f0f61c33018f8b5ba94bf23637aa97a6dc44a4da60cfefbc48464453fbb709c99e26725076bb60fb4d07e6d7eb2d02e9f7e783eaa896c017c980a6570f4e5df900cad1ff3d07d4e90bfc6edce38796f085ad11f335b856cef010067f271490317c5f187863924599c0fd33ac974d50c5540ae4f634015fdc28b50c3d031c9c1a2fc6b1f3f61eda8f0ddc3b8fe7c27e8343c3d7dd6ece0b34d30f095e696891399f821b87329807e6bb59a0e94658486854863c22534f0d379683a842ad3ca38b5da7f9923331876e76037d2f57358e73202af29475fc617b3754f253f9288c600d9e9813fe14a13515dce84a716a5e46ddeb323ed54f0d03d4104ffa4d1c95b2ff4d8d3d23a285e950981dcf178387f06cbda064cfb064f2bf90fe581d60b7093f54846c9038ae6bcd23fa9bba974483fa20d7bc9321bd34e59826165aec7cad512823716abe0aebdf2c8f4323f1a2236148882a63cee98611c69d8ee8fb3dfff7803efafb16eea3091ba8516e5cc34f7a120a95880ee97664dcc02b813eeb3e649761d391988c4c650ebe171ff066936f756bc177611d8d641530a66cd4c72e9e974bbc6035 diff --git a/zebra-test/src/vectors/orchard-shielded-data-2.txt b/zebra-test/src/vectors/orchard-shielded-data-2.txt new file mode 100644 index 00000000000..5f2e0660c6c --- /dev/null +++ b/zebra-test/src/vectors/orchard-shielded-data-2.txt @@ -0,0 +1 @@ +02520cdd57d89fc02076a954dbf96a53fa2c4a618f73abaa5f6d695a38f144bc9179998805be8d67ff6f9c5206a4e5b2f2e2d56fc52ffa9498c7ce2b2db9102439067fe4e18b02b926c04176c552baabe48f477d36a8f17fc168bafdc931dd7caf9c9d8986aabd3cc5fe448d7f2a258e152d9cfacdb6c83a77eca80088321d773e5bc765f2b9c95c0ee8d9a38aacb2e9173920cd708c9610963c7e6d8e263bab3884b8bda4ee117291018f31680bd6e4531876e5bd970baa6fbef092f042a59cc0a65fef1c5e35c50a4f6db86427d2038b091e72c3243e438ea1829fb7a9e4aaf654cbfe4f0709fa673def37b6dce171e954713d39b9f6e1a36752ca19fdc28f6184e037164194b6568cc7f0879e32885b9196e0f204795ac110ac3e60d57b3206857e375e943f25a7e761497ad957a67259d7d4ca242fd1bf5fd82f98d2d73e4e886f6ca27bebf7300aa6ed3d7d29b7143928c92ff27b59d1adff1374fde239b0e7c6c38701838ab7dcc3cf0ccfc2eac7da8666bb08fe401576f6e2f9a0d33eecdd0d9fd9bf5bc156b1f8070632a1a1e5fc16089475b268b123e3e04da619dec28e3174a3a5123d06eedbdd6d6938464aed620753c8ee192afba0b82d4f35bdd9a2db0e38f5015cb6ad81f74159424df896293408e5444ea78946e966fa1296d93dcbca05db5916f514253dfa576a64c961af8ced6f339181eddbf77a4273370a3fc19f131f348fc99e5d8796068cb5cb50c0b88dc26a87cd398855711afc4556f7b272268e8e08c93a9cdbe24cb706869582f7919a354ec737f300ed3b1bfeb6960a1815847117850432942b4b8b5092c38729c97aa69651fe9fcc4d17944e69e5e040f45bb83dafcf6e5a07a1eb1dda46f22ee4a9cb6cbb0df863335bdbae5d5404bd552c6350ddc03d78e02377a052a5d97c276c3a37ac96217056097bf0bc9655815ba7ff94d8bda1744231587354a8460c6cab4d75d3e79db2f44e7c140a86e03c1e7c7ebd10bb435de7422d1be078d882a4c07485adaa291a044afab61b96df14a72659467cdfce89ec2ba0c39b50a1b5f459bf5e9e68ec22e6372eb066134f8ded15c82538ee02b3e8829b60b9550b3209bab13346a081c51453640635f9fb7b3a41a83483b24ab09add2f3a94a13bb8da5c1041196b99fa59130c9c4418e4f5201899ba870602578807368cc2a88079900aea9c018b2abceac6eafdca68a42adac6c180285158f9782050f23f856f112c37d8739f89e952e414c8bdb4732f0f045a4b6ded87796ae3109e3733aa68e530926b9146f41bfda7a98ad64d7dc2c7ff2911b3c3c5a3c8619808a8412a0c631f1be162025dc2ef9ae2ee3f0a7f91f4eebeeda1ef603ee1d0d6288a386b745d87ed201535c036c8d04a9a591d6c1a9a714bd1d2ad8faf93955993b51ea09e6447b10f2501174f3e69d76d9c81287110367865d451ec26c6b63bec98f653f7dc06adca36902af8e7c935b88cac0402a52560c3fbaf6d1fbc89f196611ef54bb3d7a5154e6f37cf2a7f20665aba2339f89b243f79d7dc53c9aaf6e975f6c5eda9aa66c61bf7b2f571153403675b3280920978fd2f224533f5a4657a1a09e7bbbdcdfbcbf9095a28dc8ee6bdd96c0017995fcf68e565673761368f5b4a9a3a05e665f2f22bc9524312873f50d74b56d7cc60fa1495c2fe1326514564f63a6bba2a9cae95be5ac3358c386601bb0aa85f97ac97ade1b1165958085c2265d69ef8f140f130d0d8a31dcdc44cf5ee84be11236e5eb764ba5edd773567916d9263d06f97540332c579556b1bfe0f65464bb32f419e15f014dbd8e33fa70ab6c56c5c31e7d2ca3673a50e64cb4593dccb77823c34ebed29aecf581a6f6da9ccbec31d9bf51b19967c069e18dce98b3f2e1fe3be54dfc4472e74100624ed91b08e3da084b4ddd1a1d0178c99f197fba50ae21d2994a2eabcc4794b2e3f54d192e2d8b51f3c07717e69a127fe9e8f9a94b9e08c227ee9855959d535b28fe3a71090e81c52c7e23d57ad998e688073510798b5ab509999faefafa447ebedba0b36dcc88c5eb21bb63d836ce256a7dc4c3023cbb283f891b026404aad00d1cbb67027ae909a912ccffcbd15713b0253d9142f768fc30424bed82c0892486729775b3c814c9271bb14df2df851885bede538f60121405cca860a184ae2e91238761eccf07de2a1af10f4e5d829e5d0d53415bf104ff1a03bed200787efe23daa88334c3abf513b7bc4f35e0f48504f699fbdbabab0f0609b8ebe1c805aa634ade5381ae1220e9e200c4645be0feb6d647196118132485052b8caa1030a000000000000000000000000000000000000000000000000000000000000000000000000000000fd601c94102bd27ae821c48c8724461ca4be7598490673b047f4bc8b4fc2f4cc56e0a2c589e869c959547e35dd781744d93b35950d218b1df5321e5d7fa458d20a9106896e16dccfad9cd3c42c38fd0293ebc719c33e5f59d1be05c8f18f1285376fb6ca200c3d33192509c666546973e3acf46fe6bc006b0e961788dbdc02fdd7fc94499d662bfd0a479b8510f2ceca688932c64c11f20aa48899b3de221ce90afdb21e1385aa91395e04ba7c20ebd671de460c114868a27515b570d9e8fd8f248ab58bb4f5a33463fa78caf8dca1bd0080763711ba35b20e14f2ef08a52fb666a09a79747b43becd7474e7af8caa124bfcea9c0514c202a10be86cbf984fccdd123ce40e941e3f9dab5bc430ab2cb275b91373b36c3cfee84974d381c96595e4b83be3963029833aba87fcd40f67deb293fe6ef8ea3138ddaac141236ecbfaec999a5fc75e31bf013776a60cabc834854c99d1051f4d5ef58ea4904a301f89de32298e27f4466109b25238c1cffb44af80e00e3744782bada8a0de61eb9b43aef03cf85e8b4e6dd37110cde6df32f9ad778dafd5b37f6f66c145fd8200738296efa7a3587d913e1e17121e7a739969b0301d0f78950246270988975e6c9815243ba04321952c54ebedb37d208d49f954c810dd639298af279eee10c5fca2fc71abba6beef961bcbec23ecd41f7327241a9684541aab05d21cc11fb1d46f46676981f23c7362bf5439d47c9478af18db71e6c53721543764149516a169388b80befb1a4d42eb1c2c5a0d443a8600778906512f4ec54625c66f0e1cbb4dbb6fb8490ad8d86285673c547a442c362f2d16b0ce16dd6f5f604e106ead0481093f3bb9431295782026dabe388f43200f34308f674ff639c7e191ae95391707e7b720a450e0032b2087ca6d6e8a7f09267e73f5e6ba5d2d87a481070c2c090557c129a18b58e2df3a1d624c9f39ac12ba806c16bc6774c1a29c9826b6f23b63b33697a529aa5860b9095992c1bb113ec158548b287e984addca6171ab7844268dfea01c891880b6ae28bea7355f7ef4a169b7ec9d04a185c1c2809f6b8d1dacb30e40e6211c1569f52d50fff40e4130bdda2dfe91616347b41d9fd7b04f5fcd23c64a1500ae15f16ee0449706e7deccfeea1648b5f38c7947ed88494274f01bc39e59b3c90fd2728da213261042797094b5512fe7248df09c2fb74a5a617444206c3dcddbbc36ce8f01b32aebf2399f2a0fbc6901e1f09c629319d71ce8b1a6d7bd03f05aa49248578d5a19f17d94f48247c72a01ea9bfccc76da77521a30dbc9ae08da30407a79002dc3613bf930b2ef0be728a95d91fa031ccebad321cf7080315e076234d346761cd80d2bd433d87b658fdf882b2093ea822f58030ebf92b3b970311046d05601b65d24fce2db0fafdba247e871c6b9e37e2fd9c1410e65535c36063b50420c43fa5adcdd86f5d5b25e5a5deb9d5189d3d5146a7723f7db00521c76b901a4cbca9e56786a06a4d3297eb82c71391eb96525703995f09e400ce7bbd731630f15f382dbdad5c39b69df690ded325a53c44c6a37c48b79cee071f91bc7a2e60b98336f6ee86f556d7b89275822d2c36038d63e1582bf0881d0ca524c16309a7a54be87186157db43430ec64efdf98c939e5b0795c3c1c63b9197dc706cfac9b6fc627e2ce945e991ffc6a3996ed5a2eb602637b6ce34f7ae906a1a7924abe8bcd80c8b8ba9f60ac9c87a876aadb8eb0b3f997c0e40ffc8a2c19967f082d86680d28ffae9947e95e1e403315b2e60c2d900a15dbb5ac2a1826b0721b9f9e147eeaf12d23072523f1887f6fda58a04c55839b76e099478d880551e354d5bf3092f50a082275474d1ae0f08505299dc2b923835a0693a8991258d0fb4446e419e4e70be0d9084dd03c83dfcdd416130250f7149c383b3ee7100d60a18b52153478772f0223ef21d6f377bba0701ed4b21d622584f493457e157b5cc7a75ab933a35b8130e3b1e2f6a9dc6f61ca9e67c0b52fad01e08305922c7f36714606acaf751fbc2b5b8f37026e10eb7df119142cbe812f9b13832b35f4e233eb4372c4a28075290b01a423bf64bd41d1a21ef3c931d34c1940fb93711c9b5e9cca71b58398681085e771d8ba4d50737c8d1c8f697331bd48c29dbd61ea2f31b1560e0513e1cd6c588681afb5b60713740c712a77cee4c291d9046735f8d5e2ef8ab5b23fd53d5fb4e5d7145ede77ed786c924345906cb15ee0f84dd89a992d5f41051105f9eb03321006b47a4b6cde912046c29b7324125b3865334927eee864eaf5edaf754c88637d07679581c5e3482b6a2d669d1d6bc9688bcc6c260d6cc71dfe1a8545032433af1e2ff5fc607c10cb589a4e3fefda6374a082070016acaa081dd3b8039226c71f7518a638e5ddc88320bcc463c21a15d76367969bef0773883eed213876ec69d0cc85a65b8d0708976cbcd2c7cf527ef555b616a91fc2eb86398427f109a66c857a8eead0bbb3acf462d81f4c74bc3246c0f9e636253f12ffcbae36ec00361ebf95747f46a5a15c0acff251ecddb1dca9bcdc48e825be643202b92dbd40866033ce350ce3c1d03e44e72bb964a89dbf2a8e411fb72d462930bf1c0ec057e99088e9c3c650eca46538e8b9f6a15e403a325998cc90a705f8acaa742200cf6082617b8a5e474b0853efcad1e87c6bccb0fde80b6c8f1871765d930608c26ee13bf18058ea43d8eab58abde77cbe8fd7581e934fd0bb22ab6d81b7a135afda3c78bd4afbb6cf98472585710cbb4560401d3bbb6e7cf9bfb4e79a35121f02a5433e5eb1225a67f4ead84a22f1c9e1de3c3635a26cfca3886c829ed20c3ae36bc858f9e91b382d289fe7ae3da8fa71a77d8ad73f1ea5e49df7e1e51748050064d19d16791ce96e65ada3353f8acf78dd7125096eee11fbf42d619c457f02f3a3c28b725d7bcef8c3dfb353445c3bc2991f619beccab2e11718186f3e1a0e9c922be0ab5627f44e077c2fab8de26f2fd919f6704c89268b4f5c3b8ddef0024738099823edd1abe5e2aa20240d9be73dc85948d7d54869488bcdb1bbad073c5a3c94f859dca674a99abb08dda84ddf94e54e90bd9fdcc56d18b782b1ab3a0b6fcb4494a9499d95489c73a476eef8e000333f4e1883298f4a11b49f008d5e2666f47339f626d0768e114cfc3dab5af009dee8c166ca33da0ff6fa3ae938ed0e09c63292db410b550f4376541f87f38061453e4d831770e34768030a84e4801218bc037a1a9fb1ded2b96e960324d3f586b8d90d75b7d0bbcf3436920275bd02fb10ca28ab8f9ac42a57f8928a5eaa90716b2dc75188e26f770449553693540741ef3594ab803477083409c518cd4ffd8c5631801effc61b035e5d83d3941535eaa5bc419cf692448ccebe4b3b2f701af49d0a010298ca7b3e2388dd75f0670d15ad649a4519365a4ea7a1a9df4af41f2abf0c7742d17101f5af5c23e312fa3ed2863a87870b245fdf21bce3b2d707707857db41a9b10830c0c2bf2348438420e613fa2d9feddabc9814a5ddbdba01df46f946c71d0e522263c872930ec7a1340b59c8132b3fb8b6bcb4efc00e7b96d2340e4b2df5d8a3a11ef12a6247a3872a05bb7184e9668797c605af2a85ebb8b103bb3f62a9e03382379ace880ad38d1a07b0d0fcd0226c327241c72536b8060870ca5329446e706e0f7b96ba1c366825f793c39b60597b81a56abb708bc2c60227342ad7fe45aebb8bc9fc93e527363917366df5a30566286afd722bdfe3439f079ef83e84c52862375b95c4ee966b37d7ff1f5dcb60b0ca851386d0e10acc8722e26711ac266d9f6de5bdfc540a0b21cbe76397f1e9e957365992c6196ca5f6e5cdb2e63790714b4f6feee7e84f4b0901d4e5c81f3b9c4b87f811351cddae43ab10a002caa6e7e4b0cd088cda78563c8bc0bafecaf12b4b320be1dddbf10081411b2542ec1f2cd453dec3690e2e2e017b8ff4f471f17ae24646cae4bd55bb03165d7ba50f46b496d3681d7fe829f2120d5554c13a63f3ab944af91adcef1bdb36dbebc931bc5ff673c5008e5264ce2e57472a07052bd9ebb282a68b1402e06ca605ea74abd1210701193dbdb3461f18e424b79597bdd3c070072c438cc1a15afde6a12b69defd8739c89a113122b03f81ca070959ec23472bdd575d4d78c19a460dbfc238906eb5b1d66f64a8a01f204fa9fb4e808233153878341cafbdc5332268e094f13ca677dbe5adc5fd6753106866e3332abff7401f76b848c5e96114b9d7acb57206192edb2b995d7f1bad2a5f682553e23218654db3bb1360989593d820507c969c7524a2dceb3859fdcc1709f9e45e612b2c7431587c7a2dcb9d9a0d6cf7ceb58230247d3e765d001e461b076c46c7349ab799d0826ec3de43e29471f063af1295473bcdf9c2161f05440e4b96d8d323d5d49032b5ee541dc92679d0b108b8bad6b0577877ff8047f36b3ec846a9c62bb0589b3eca7054f2fd45b7e77c903efa986a3bd8e2d534db28cc06f3e607b5efec7bf9f801eeee60ee0f3d7209fdec34cdd92f6d132b323d713523409f0238d8eafbdd1684c054d081a6fce2e71836090ffaae2c137fc140f2dc178fd14a774b7cab1701efc9eaf3950578075240af5ae45cedc499d54fba608f3f843d0c8e9595cfabd78cd006594597f24748611a352326cbb50e09c5617ef615777a5332e3abca10594733417b848d5c03d2a812283d813bda13fed7bf302815afca628e54bc314a304cb45d25f67e7d8d489632cc95bf28d0ec35a53379991180c63966354c26cad350c3cc90eacb58d4f713cdaf29cd293e842b731d390a2d2ef4ecafdfd3172dd097666d34c36d8f852c05b2a7def986b6ec3534e2f7c415fb0d3c20c7229bbf93bb787e8a3325ce51e48d1ece51b10c207f5a89b75d0703a4595427139973d3bad2fa73eb227cefdeeb898391cd4efef45a50ea4b7a1121efb9592e7c0940e35e0f6eaf5c9685f32387475f7f6e75dca843497a4d19fc127d3f3675a08a69af324cefc5952a8d24c0f72daae81eac5bc979a183e94ec000354c8dd4e9c0b310b648f302601fb5359d567144c1fc34bbb1caca8ab283272929e5a2319c8c7ffdb7304e1c2bb677f9186907672f1a4064a363ce68d81ea72faa29594127c5236c964e126e06d622363e1a95fa4f347ff7dbf95b0547dc3e3fe0c1a8bcbaa41dd8be9706edecf7c4c1f5b83e3e6b7220c3a5ec9990aa6c4b1487528f4b03a8f8caafdc8876f646ff2b5a3b2c7c5f6cf99598167744f8c3be0f4665d39ed1616b6b8bf29a9a93e64bb53640ad8148ae2a274e64d995a9262635b7f500ae2ce92d71db16dd0f55d71272d40540433c4c95feab82390bf49cc336bef8a3075595f618b75c4bb99f52923aa6c7fff1fa75e0ebe4959b4786807c1081ba4407802c6b95e8523f8b423cb38c7a234c0ba2e8f8e63d86e2f123f9a90b5763be618c4367dc72166bd2264208ae135f2e3b7d04e82e9873acd020156a15fc66676cd6f1fb2ce73b13690ca1c37700b936745acb5c61150a669b9599c32f58968f60edd228bb64503e7da7e2fb9c12da3613d3e331f87b57519656764838f0c75560a769ce6ca379ccbc43d4ba3dc3f9b9ab1266aad4b36ae10d90d8a73ebff98659cf7a45a018687c790beaeb4c8052bda14fe0574196fd23c0dce3f50a7e07ec6029dbbca67c68662462d620b754924ccadd736459f6c39050ff27a91e3078e82f858e4d5543589d3609ba28948106560610178d27cf15a9d5da8b52072ccdfc4eb3d00a913273e0e37af85d30cc14d4a7fdd44e05e55e777ce8cea82d14f69de51559697a016eebf9b4863a16e9a753b980dd28fd33894a9c1360b03865616b87e46e0341ef151488efe703951716b58cdbb444e3ce2c515651e5c3307d9aa4af637bf2ea8216a9782b5420fa2d8c9747a7b21ad24cee7a3dee90080878ff796995f67d65f5072179411028d371bfd697e7c74bfe9b5944fd1f3c463ca42846a531c2a057c1386676d36f3d1b30c2ada3e765d018dff381690b44bc308c54976f1bacfd7d5ac613e5d5aa3551b0e08500a6da06d1215763b689e8c9031490aab0a79255e23fbc3dd0b93c53c87a83890120a4d8b9f9b72e2daf30611d7b5d90ccb5634fdc40cc3b815b8718d7209c24f6f88edfa3081139ad31e88233341128216b637424c91029db7d571fa3e6feef1b5706b2e8a4e3cff7cd29100db1414838b5b87b1bb082f181f8d8b969147da23de3873e31881c51cc3c187a1e3b423643e68fbcffe8ee97ea9cf71ff71fc3600e97ed96bc2ed89744d798051530d09965a57ea7db9251c67b0ed7beb6879bed79047754ba2f3ef2f4b80d943277569a539bf8f61ad11638d729c86d774342b1640c2a55fa5a2412a1cdd6c11aca780c72f7ad71c2f81f6fe24b4810d4b1d82366f05c0ec6e1df10a0be33393ed3f09ecc500c3123180be606d8d816a79e11a4a32f4054512d5411fb02a97c1472420769295bc17bf56f21ffb8d8802672e30a0e2a63905f216f46536e12c9094b423fecdb05fa40029f3db7b651e36a130df6d1dc0bedd7f584e0a02e9eb31eb2dfca96e4fa11b3b41db4faefd35e67f182b27704118498a3b60d6d96e6661a286a9589b83f3fd7009da0707cb98bdd4e986fd04db1012d0e966b6bf6dc42224762c6cd076368cfa791044bfe21a4e3fee47a5b311bd8b36122a3fa640c212c37144e501e1a14754b55c561f92db534eb4bb4d736f1d4f72c98550b25a16139ce3038721087487a366369ca7db475b6a0c5bac81a12276ce85d816a822d8d0b57882f10108db2ee1ff4a81d65c3384d149a891eaa6330b67bf66fd65c456e20c92a89bcb569a08c58c55dee8e912ffaa20ad2c48ac3797f963375994750800a302c8de1752d88003050e4faf4bd43b4712f29c7450123465525d652f2eb6f2938d4bb7b085db6d5027d8561a17ae40c5f915782a743382a92ede5243e9fe720ba35af94d2c53323bca5e92a33c5d6c351f5b7eff20ce2e61346fc7dedd06d1c82b24b4659c4ebaebc2a0e08a296a215c14ddc7380451be056b56096a2404f26ff7b9e4e9d72fb2640d7b9a130649df207645bbb35d085c98669c0a23ab6291da2386ef934da7ef007a4a562da0da4ef847bbe84d2cf70f2095d0f5a280eda095dfdf3bb7c20912338d9506b247e29414d74a5ace3a6572792d4b394dc8c982961056567034e92fd53b1dae2176378151f05ce4ab21ce4409b961c43afd27d1fbf0ffa8c9f30476df8e1bea3061abd9996b4f2a8cbdb5a786294654981423d2e3b065a6094fc3431508b3c815fe732085913b6404cfc3945aaa2e02fa4f2c2232ea13c3b286f85d21857a10af7d077c799774da00898d9f4a19920d829c1f4103b6fb6327a75c4fa5eb3c15d495d84fb6307289ac78757e9fa199059bf79c83a8cb4584f706cd700a4323806085555adf36f658eb7e394e22c6bde459215a22cefb4101b8c64a70467fc6ccb452ca269fae3c3feb0075dc57663c17bf4ce5332348d55704fc5528290092f3005d261c5698d8f0124240aad87cc04f972e7bb12f8909d3344b880e98eba5e23b8797d798129c2ee54b8beae102e179e75954e1d93e9f490b99f0143b5c566e48fa2941952cfd9fc3a3c55a1cebd0896b7a58412cd8b3ceccf35ee3e7b2d21454b551f35b577c7f478029d1311d0b6f908d71d1a0f1b85ed92cbe9b96e709bde7fe421b3b94f82b7a4a6bba04cad69f6848cf404e186a87c6b44947b6a035fdb17657663572e81371cb7a56c94a99e5b430d4c156bbc311f1c66e83915069f2988cd84330203a2e029db308a4fad19492d488b22d23950c92e91fee4e7a1756615ca92aaad184d5af42a4b9a3fb8f6b7ba3fc43e99661a097d5cbe02d36e4d2f1be53a892a3e2344d67bbbfd8ace93844785a4285c6e8fb4766fa2b1c8aa99fabae2c38f511f5c6ba97df7888c9dff4b41bd8b29e0799503018c246c585ef9e6d5e5b6e95920314f6fafec3903569c4530a65f17f49856b0783fd575ae289e1ff5c11ddba07d868685472043d6ebcc83c7a529367fa390d57f129ce0d12d532b23bf9596d1677dccb8c1fbfc53bc5825c9ddc424ccb48f759733c2ef47e6e2d174222baf394c146c1539a2de78333caa0099362f304c379fbb1efe8aae95e0a7e37cd9a3a782c6be6ef6aa1e5579f95e38f54415c546c00559ec0ba80a9e522df7f28b6ab768660d5ea6da30bd349e9e2db8fd31fbe2d19592fb05a2521ba70e1e906333aaed60fc91de821a87299f46b2479c0e1c0e0f27f889907eed6c7e7971480f810d9c74e1406fb54dfbbd37fc32ec3c232339b42929c9a1d6444665b1edf3282e7a4ca16d76c51efd22a94208a9ffc10a7d64e5f3c6e9c4995db11417bee89cf93671030851d43b18f583e7f7033a8a236e82ef16d8f301b9201db31eeeb8ec5770e28066169d1d07f1deadbb8690ce1bd4f61b22729df8472fe319f46d2ad056b5bd8fbdc8c81ce922db9cc8f5420c01e6c696443f75a268cb84451e91ca22eb150bc57b9be304eaf7fc3f8f09188f387e53eca84c01b4920eb6c05c355fbf10bef828cc457f661313f906dd05e51815c53ef48c649dec558364a5f4f16217c521a1215a0d12ba9cf48e521c4ebd8602baea537e0261d5824d20608a6c7ce9f5f00d13685a7b43e2b362242a68c9cc1fe0d20c80ea95e7e2fe2d3cf9b57defeb39553a43b127af70c637b50f5a5ce132c8b40d974dab8e739e99a0094602bb0669116e0e6d659cd543b29fc6d26c7a0bc6d86b1e91f194a4bb0063fe6d4dfbfb3f55fe856ed8265324a8e2ae556589006a7ac7c8dd44eb5de6a90163f9732dd8fae05e76c83027d22c86fcc8871b90addeaaa1450690b7e6587d712573e2003bc09bd0a0752087ddd0b852323d739b2c579a0c6439084eb1e39b7b40801f4b664ec154b736f0e006c7cb13dc2e324f10b5db66bd1db228249ffdb4eeb9ca3a2790838131b7b9bcb8698098b77a1be00a80ced3feb2e4ad516caa85fc0e42ccb7da4fad858d5e52f746c738da10102111a689034fc1e2f16e0ff045a3ae6d277b1c0d79251ddfe933365545fcdc2c5c1fdca8db2c6f0f6fb85084daeaf0ee08e3d9d05c01794221f328c5984216c8e68115c6b97fcfd4140da5dfe04ce432e6b6b977f669a6b72e6bc6ca9407d59d35001c4ce64728eb43f7036885730720d285e67dcdcaf01b9ad8833fa11b854c7fb659665b55da025d1d4ec5f7d4bb552837a4ba442736cb4b6aadd71045b06f4f15ef95e22a9a8d83ef8ae6390a20f1b79ff35eb8046de0eb8eeb9bf3be963f5ab129e7e49a26805f4b810484bd5195291d7366c71140cb06d6f19c0743f59bbf0ea0b735b83c07e5748a632df0fdaf0b01fcc5270bab9db7a36f429eedbafe36372f2efc9dadd03995990f1c598254b95feb333582e9f411b1a4578a282ea94884d82f8d0433f90e257a88555b45e2b99f42b7dfaaac5b1812d88c2d419d70351dd0c79403bce305f2fcbefb0a730210307fb2e85ffafda5d31279244a62713d21c4ce5e4ceac1812abb603773c7ff9700452987cb74f3d97fbc965e991fc32988bba1238a6c0ee808d377e10c8edb9ad1d174de00e12ef76812b555d5ee8c82188099effa0e372cbafd336e3dd65b54286528dc2d51010ea752f59e8b40148d899094410e08459960ba7fb505ded2b71d71bb344ee5a43fc7cd0b9b4101e2193f0fd6deec76ae16f8b9accd15328ba4704a3a2db760d23dc64d5c46af5ea41e8c09bbc74b3dd48dc89c983d3a06c6a672f49f7ef9695359f2cf6a8c98eef41b8fa13fdd2fdf04965a0c0cbc534f036b89a3c6e5532c020c2c4a7f238463c7a3b6e457a6020fec0f19fe172963acd6c645ed4a2fa1cb8037388e00a4fe8d4d1e8bca6a263f0dd2a8c847e799c4e5437c61e757b49a90f56307aeae31dd02db7db87c9727076e590adc895c3d500cd1ff1c12769706d0aaceed25ef3e759929be9b8a402115040228cdaa2905e960a4587571659064271bd6dbedb856fad86ac5a3052a7b23472e8bba85ab79f0d380870f963df77afc7d393463119246aae20022cb201c881f2ac2753a9ca6119f17d7efc638a45c2a4a07bf9135ddb43555ce3f9c769cd4652aef2283549fe0e02bb785b2a96725f6cac415a58b60149327930a679479a7a8880afbc912e86debcca039a1fef4f75853ba614e92ddd5b4c44d3813be565b1b37c30f70703ae5ccb554a55f948edc526a3e780f8e5fef08246fae9b2963bb146fef0e5a7f23b09299f00683844c372d12a9e3e9be6f404fba8e3e85598cc78e822dc7cc996a9d419d323388c85a274752fe84796dcd19b6cf292f44a3650ad400b9bcd0d66ffa7b9107413fa6b52783cb3114e55c618243ea88132f46cb6187ad313d42fa2314e4150ef2ff45e6d37068d5bb35155ef164ff91b550377d0424c3f2d86cbcd79384d902e986a0eb33b53b098fd10ea08103e11128 diff --git a/zebra-test/src/vectors/orchard-shielded-data-3.txt b/zebra-test/src/vectors/orchard-shielded-data-3.txt new file mode 100644 index 00000000000..a1e9aeed734 --- /dev/null +++ b/zebra-test/src/vectors/orchard-shielded-data-3.txt @@ -0,0 +1 @@ +038bbed0eea64e53a836cb658a81ccbee399066d13ae228fd522b72005c634c32efc8a0c8af8efb5e8e787aa81878ce795448a10da0338fa656878172617e9d1023ddb4b0c06d73de4b93ee138d69fe5ee5a8a4805a4d9ed68d82398673a9b613418695f4451acc0e637458f50083e37bc6b6c150bec8b14cf8753a67b1b813933f3083f93912ec4fa9a197a60c2c3ed12938769ee9aebd0b5cdfd559b998ec38abfc92eac5f7bc1dbf15cf0a5e3ff583e7e93962779526da764e511c503fc81f2702b4f394e5c8f235c51827730d79c29ae113da8fc57373236b5dfddc390df95e60a2ccd18ed567afcf72908e2348d7e37d788572c1f8af169e243f2b7ea734d2805ac711b2fd21660e319be03998f0b92db88b25697584170cd8e0a66829f6b86ef9b37127d3ee990d79adeddb2b42fed879d0164246f0c2f3c6c488f7ada3d55bcf98baa6c59f75c6035dfefe06e92a9e581ee78c3b228bc1d0786ad35b4dc512a5f5ee61a6cb05edd7c7255e6b63b3de0a1adf6c3566cf48ba798255575f1f7661179f16839e132b9931059e4ade7f403804d2f67b8819fd4dc1c188acdc962c8f80709669f0da9dd0d71be404eb30b46226457e77e9c70809f87f8bee97a4bd1101642c13f664102c87d42571eabf1fcd8f1a5cf126879e78519bc02c655fa3eb84b36607b36024a3e3288e10345154117119c61d3ab15cdf956d6a1e0748d21556c225ebc5fac32b7f5af3c6d021521651684e0b6e99cff393e20f7bb3c1e07509ded8ff29c1f3aa6e693c12012610144f82b6a31b14f339cfa8eda191c87aea675567c974c3955fd332f3a473fd6e8094167bee64b4ac039cf4e1bb2904307a44eb891c3716ca58facefdbf917afd8bb6b4c82307e7fff081ecd18c2d20e4d5f6e37c57ba994b9131827b8a4fc3f0b687de6c14e4d9deff9850d2b4835f95433e9fdde0159b8a6d89b5e01c052866a85e4cc813727cbf351e2505be63b486e11b1fb6344cd237824c0f2fdea0dfc234f67aa937b84a03cba9cf2f645751d5e8e8858feb2c6b05198f4a5f38d6b9a1b63a6ca463919b34afea26d00fd58ebb557c3af00fe60c9662aebd9a2ca409c0ec85f7378046dba0aa8d1d4a01739ac7a52cb81cf5ed79201c596e7571dda61f246af632ac2165692a77fe84975a2be143f2ba97bf74717d5eba89f9ab1e3c86ec509ef8a06c8e784d58fd7b6606cc0ee46aac629ef6093ca7fca4829d324d6100d358e536214c60ea702d77b50b2b60089a41300fe24b25f0223eaffa7e13bc03a33087e67800d1cd6b443a3eb485c637c4328b6030067a721d89bf43f1d74ba84151062eb7e06d776a36a126aef289e0b69a9da11be97c79210f82d3f8236c5c21cec2c237733204ed245fe171fddc036496e543c5321d3747d1af5a4229d04f57a45ca8be67bb518064823d900c32e01ff22585271a8c677e690d1a65084bac6691e9bc97a07a016abe5be9ba3d4b0e36326dadce76f5bdcfad6b779b8ebf6bf7feca6eb55f0879a0d73ceeae890d7e13eff56219058f1c8cac0dae07884ad0cafd07abeb52eb2dafa035193e6bcbfa51941e26977d4e2771d2eb7ea65e10ca868abe5690788ae66ec1136bcec8bce4854d4e2e5be6aa154a4e40f8d0ea144e8e1ca8cd7f8e203b0f05c3f2f6ace4b716a211c89fb1774daae3f2d82870adbec5802e4d3f35a211e8a93e04f855caaebf54220280bbcf8d943b3d734324324cf9658065f8083c8fdf6918bd5443f7fda3b618f0a79cab02dcab66847e4372b5400afe1132af4a77bf27826548afc33310e5dd21fd4c7a229bea19c5316478e57228a14475302806382972aeb24ed6325e32b42374148d179ca4c9145e674504844e3272461bfcba5e566f26f9fc0d11bd920751a7da806f735fdef2d32bf4386b436ce920a66b52fb2b1d70792dc051a2df4fbf36e9b7a53e3c34e2cbb15f47cedad766a38b66ab119afb12753067a23f0e35f6bee30fbd885cc0f361e5a0657ca8ae5e2eadc4bfeb23e00d946f3b6c0da72352c85d415bd892cfc3a63b60ebdbcb6d5a93ce6bd80e9236085eadae1876403b7bc5eb3018c49088f27709ab764c35edbf197ab55a8ff32f973b23c4f8b7c3cf280990e709bcc8993db5a52d1add3c2497abf1ebc891e7dc4f46f2d992d18964f832dd7b358a6b475b4e07fa6220796c6e750433cfc7d7975f0a5e801ef5e218259b636d46d64c60832315814408e1e9bf004a96187966f42aeb3ce50e42752af9331aded60a895ba4c310190ca5fcf75362174706a6ee0ab3696b2c96d49363d1cc5dd87eb879ba14d61eea15ba820db9fe761d1d1b34077922844d15c8b8687fc97573d0a6bb60f099a8a5c797960f9266f0d824e40eff824d821f9616bb41fa61077fb0a9fcee9f908325d7c7cb2e31fddfcf86972ccc6950d9c306a0af05b08070113e429c24ccd8663a279d31a575d9c7b63e69ea6e109cf7e3e690ae2bafd1ca5e95860f5cbd59d957b18f5da9a1364ba83d4e6bfeed0163d5b10a61b4a0190129b2cf5ad76529465622f754bddb6b8d145d4bf963d926e1295b7f889e761ca8f623646b23ccd12a36fcfabd4d0986ff2b52b801fedd9241ab1153cc1df4ea2d6daef950f399093f0d1944dc2ca40528603d5987e78174b92a7eb61b2b231a8d461e80b6ea754d19bb38cab65aec4c01a99f07da7dc408b812adc5cfbd26b71495bc6cb8e48e6d8ef7adcf4737e5a9333f04a68def528f7458df64c04f5924acecb2ad9c066e358f454d0618b3900d376c2b401601ac15123581290b7f192e45cb7b62ec633425799f54a98d0d1e313119021c1cba2b37a1bc8c43489eee760f2f2d0b4db6d37412612d7d9a64ab957edd47e8f5cf5bafbacf994e8744a3b74c5923077af90c7c9884e96ece3d652d2dc5702d7b6dc698a7011749fca8bd4143ded78a15c1303e8013da864b508e1d89f22c2f098959416fc8d7fad8ece82ef556b696acd3026d77683a12e7a286103be987c8db4ba534cc95500517e4b5f278f9afcef5e7f728c4923ee442f96bcbc099a6e187097dcabca2217b04c4f1c3cd81b96942f3aa74b326e57a9e052daa657d0159f65e9a6570c5d11fac90cb8705ec931e1717f3b6f7b03e3ece960a37e4b8267f4ed9f124f7a750be9741805d55ad6740db768b968d021b941f7b2cf862d413fed8c266f865b228d7a19c314cfc73149371044383ceb655f2345e9ef7ea6cf8f9e1a546018a87c6286ccde22bb04459351acec45958599b1c57c8acfdb11cc1ccbbcc583694c131090a61e735e334151818004b33f0b83b6062aa767c36d94e322299a14b75ce6357df26f3238426eb2e025cd6d84881ff1913e82c598377c75f53f026e8a18f9b490929df94becdef9676b53f5685b2d7264ab92e04b403cb12a57a5dc8d0c20de2dee8f09f42277f6a92d21e29c7c839fec6d59c572be0b8158030a000000000000000000000000000000000000000000000000000000000000000000000000000000fd40256165fcc35cec152a1fb4893fd25e648a8cf6e3a8142ee0eeda72d68fa6293a97b2f33121505e2bd4c4ce8aeca9e59429acb5a8f50ebbcd31bdbb26f01f34d689dd5ae1912ac14bff0b5e512e1e5f9b20b414c7576b361c0c9c4016f084887db83c237600f97272e4e479825b4ae1a34817929052a98eb80aa379a82c726799188042d9f285fc0475ad362e7e436bd1a09a46b939b23980d8be0e34266dc7e8872073f00c177a0f600c00ce3863ce1615ebb80ebde29388da1fd9865e4893b23dd492ca6b76cdda13748099506cf85df17bf9e7ff2e4e9bb6ebee3777a923a788476aef564b488fbec21167e2770e8bd578a09d4b74ffa7200600582b4e796990743d4837ea4d12eac18a24095c65044578344541569f335182ab5eb1e65b43b6f060a668bdbacaf39ecb5070378e2f6f73a35e1ae574371ca1b11509a22d0826554d830e6d62cc21f1c2bfe31b4672512a547a48f4861654a329c449782b2d378e49b16a83ba9ecacb3ff612ede89ac2b9cdd34ecd9d3d896ac302f9b653662632eb8cda4e58ca207f2d85e898369994cb81af0d311466b23881855267d3bcb5f4937186bdf06d52e06bef329406d3fd1f7b58753d765a3ad6bdbbd4ec9b2c9028686772cfddeced1d522f6db6ad30026599e58eb747bff456af0faa10db2d13f60724c583907ddadf04039e57f287090e649d558ef0f7067efa9323a2231239c89bc6e80b7228d9348d6949a0b8f19e5e086a7d7d68d7606c5fab65e63a02bcb1350f0cb0181865d3f276decfbecb6ebeab19067161748fa06fa39cc986533e2451f64745eaa7d3c0a6add6c3f497114edb10c129f8ca3c3658287ecd998eba3c0bbaa8cac168ac167c5c0abd062e533dc9b9c6de84f1d6ced42d023cc374b6e44985f3d79bb2b149aff53e2f1c801580bb660210587a601979914d0ae0273785addb9700c6cbd44973ce545f6c3437c0455354ba291e93ed055aaea4667b1a319081026bc3e23bde36aabd9f78bfdab88efc9ff75678e68f622ac8a40ff2128b8292148b5ab73df56de8b3bd7d2f32c262a30945aee69c556306eb409c973b600e68e0c5fde9a514b0d9191487615b41841fe5b5b12447cf7f0fb50aaf1d857afc6b0d255164c2bfc1537b452102d5cda3eaea5325ee411a326a50001290bce7ba572c366d4fa501b5bfd9463e9dc8d2b3c69d87ba0bc3f99cf89025394737e74d49edbe483860c79a8ad536b9882e7434bf605911db21ccf0f7e7b8e7a0a91c753ba15db2ab00994aaa6d08761a3f19e0f2b43f2d450d4207b6b839ebd03a0512de2eeff33b68e9baea0d42a5a4facd70ecdbb73087f60be1194cc9149fb62850f1adeab5702ef36f89129ce7d3a5a64f5d411f2c4c2d9482a7f844df06a6a435eac45e683c7746aae3d406ed5fab8f64bde516704fb564c74911a7c1e612573516906e4093fc79457780ccb19208271cefa42b3d2151725702c6e5fca42bdf3b51946f714b71d1976f2270be47a5a16d0f6d7d201968531c3544b8a5ee9172adf63149a34838af59648e2334f55602da8cdbc6919dfd014f4abe64e0dbaae767fa9a97c42a2a62ada89d77293382443b84aa088a85fb75fa5852e9db1f9a834480f0c351824cf0a3919c7794a68422f62ee1817bd64ac4533691649f37a3ca8a4232cd811781b8169de9583d3d111738ac501bd349f8c346b73b4a47d70ee03d29fe94f35b1bb40fad490b8e87820aadb3c310efa4f1cca8ec1878e7ce12532940f1ac021b7a01bdabcfe2b8bf6c66d187859b3762025cea9fc83af9aa1ea1c0445c2feb41e53cb372743c0f1650b9f12c4282414736ba0beddb72d32b8b9497816495438cc7ad71c13ab3fdfc7a9662695462bd6ea9a08929a8a98b23125226a460f7e1bed1edecb5ccd9509c4363f1625a00eddead2c98a93cf15907ac6d14fe09e0e8d1395b417875ae4afa3945fc9f625965b15cc04d4314bf9408a5a3152e480efa0e8c9e1d26ca0f493ecdc16707c354e39fc60a0e4431b1cb209196e1449480e86e17ab7d53c2b86836287dafa2030558eaba4c7f897c1a7272b196afaa42dda235dd6be588014dd682e48be2d4fc2b4f7db370d1b3aae3b88a367803c8c167400452329d03668f13f9086568eb8202349bf906cf19387903a184d6968d71fd4471afd68655efd5a2d42bce2a7521ed25a09ea89870d3fb4d3cb7c41fa9b117b9152ff70b1a1e37309dd13d80603a24a1ff086e98abd282e2459b47afc7e96b97a6212607f590e0c8aa0d88224e9cb950c5c779203617cdcd05171281e243b28e443048ff71991ee1041fc2cc3cb1c7b102ba3ee6628aa8fd9c322efd5a2652425caf02aa07aacd7efe0e9b0f6d7708dd9952805da16b1d23d41488206b864ba49c248d53e4f359f913743eb8eddb889f5562a0ef8080adc9e2bb89a6bb352d043afb8588e58629915d93a3af682e0ebfa6584ce8aa6b1a9ca2bc5f88c5b80ae8b741d5cdae55fa522c289274ecb9da9c9087e00bac4792700104950beb9cec8f4ddc2aff57dace6733e68d3311effc9088bb1775fb6c4bd4720ffb667486b43e5a573283422263eb3a8d94e572c451ddded4670c955c3f53d331d73fb97eebc22a70525785cb44c2bb9f7434890f32834bb5877a23d7cdfcd5a77e711df310f13756809b595e9e0953694b1ecbf1e808b06e42e89f7309bee81282305ab300476e63d1ccf33d41775b67551f39c4177c84616ab92479c9caaa1f8a8abf69b80af537b6ee071673543ad9bc89923d6e0dd9e596eccffd288ece1768fbac7008efe20f58508e0c6bfd19a3b346bed83de90139400b31d0d45d4839af25fe38a20b8e630f931fc29b916f5966f884f3196d9b7b3539d842937820b89572b291a0ffa1c091bf82d6a2c63464138482b064de08c80f60f202b176d03877a7e2d11653354b527bd9c70de4f22975727fa6c8356bad45d65f5104e877a0277610f264f013e369e29d738573f385512c69e2a502938b38b0ca5e629622a002de947acf1bcfcd1f9fa6c3c6557622ee31477f5bd08ef7050a32951e93b800868c2861e9200ecd0312d70e0684a80e38e870ccdcbfee5440d1f779723d792eecedd08fd73f0e09c2c0868beb51cd19009c9bf8fef9f71688e6207ae6f9590b4be263143b9eb92e7a569011b11d5a50be700b6d8f91d6504cd636b7c6e42800ae4c99fbf212ee1f103d3b8944c001c7c9bf56f511cebd4e69b3c4068da69017efa2fb51c449461065a0eea324326f6423e2a3bd5f15e0e6d6de3b9c25863a3569eba1fdfb9c4cf43b4b4416578f318e28557277ca94656f3edf05f18ba010b1db381c0aa907fc17a79a26ffab3066b010242dd172360093cf6cb1dfd485e41aaf5c2bba215ff7458fbe3dab25bbdf102c50ed481bee41a719249f32af8cca3ff4053a925ef0315aa9cfbc88696234c1db068beedb52fa332e80028d44803405859e6475099e6512231d51a80c5b5511e916cf0b6673cc2b557e66b0e7d45510bd63d0fa451542cff88d97b4aa6964e68206913134b03a78bf4e845250a050020970e29808f1e91a4bd303c3f7897a8dbc9cb8a12f5fa6c2acec72794b2ab63509ef1f48d424baa561c14d2934d11335d52fe899b2b9720e6b9a7916eb5bf03835bb718a3b7cf88016966c324893965fa597af0d3d94b0f57fb8505bff62582bcbf2594b9d3df5ea583e1fd4ecf95876b905710bcff11a38174b3006c00a7522006d3739370f24e2037c813a24a40b874be512130c2a9f9350b368fc9b4e260d8e20b77de78b94770169f292a019aea90bc6e435e0c3ea383516c635ed8a8e254b5aa4348a8b16693128b689e7db0e153eb8a0d99a38ce6104741a9e8ee5e31f906b59b830f003e4dafd1c7fb92f1d0a238886ca923b347ae8504af5e4ffba11a1b76b09fa3a90794c934f26de72939bd0e0a988c2ecf2ca146b93804cd79406d2b07ac629ae247f5f2cf00cf479d36c0747b10fb815e13eb41ef98227d3202093592eaeb38def22cfb9dfa93d5a95c289092c689627907c720893cf574c1225808be4c4a51822dc7050ba41489e39a0dc9869bc67280c4285c13d4fd13c8f08310f408705abc3063ed5995b60def5d07b0de79d0b56b61f5c9d5d6f65061434725df2b80b19f268aed4d71bc4b6a7b804505b9c9b4dac1fd0467491d8cb893eb7f6bfa9b348166039c75348f398a12b4981d7494d274be0b215398735162b3cb2d3ac5b3af4aa8c364914e0e1e3454bdfe85f51ed48fc58b32f2334bec96506fbc5142d8dcb1992449f5fddf6b51e339d6dc3c266ed5094d4cace2cde73962c746c171838add0db164fcd61ba512482d86e9611b4343177c87c830487d74b0b2fef9dde3ad8ff49a249380f68421fc21fe1ff3044bbfa84a080c365efd1ed02af4072a17f080449fbff17bc10fe693bb7961b006091d739123fa4497b2ab70f4c2f64a8f2981baefeb26ad794bd9be692d70d18d828e9d69a602823f0fc3427377c99f3e24b1ea50b0a746dd5512b88e8f274ff684ed901d2a7e7885cfcb0000da86f1cff90f859993a496d9ced536e27b0c4dc52c8448c7b0a47b3479d382f5d22b08a0c7a2fd9d25716d85354e55ae74599815d1850d9d762ffd593b37e28b5c4d623554f68d28d6b7d605bf084599626f4a407b602b88480dadafd2f733ad49dc1efbb53c23ffaddf15c5201cdc86219314c53ab71b5255c252b50683925ab1f26027d0e39cf5c4ba59ff5ee96f747f686a3195043e9957cb6d67e7dcb390b60d64e3f1da7269c6c0f5d052da8209e4ced0819e1d1f0f6c75c4d488a4f146a52974ceb188fec823f051a65b706e8916f00652300651662fb24b5f8eabe218d702876ba59da219e45f59bf2420e30e71a5ac4b383ec023e1bd6fc5169f31742c0b7d60de6d379e932b6cd0352274ac74f336219c583a8b9333ea572ec99314880ede2455031da54a4601cc7baee4635985982b11b5681c09f42f386cb8d24bb6212f572c32d62355093c9efefc62afa042e5ed24a95f815a6308ea60a8d0c1683ef1394b9fdf7fb719cea0fa8d81f88a3ab803a4c9a0fb8a8429249eb8e105e8c3fa18bcdc3b769928767360fca5f744b2a6701c10d1924bef74e69649b33259d52d57b67f63ce97c1d4f99becbde572070e97c514d77b8cf6fef55e02434cc16b4f1ca6ca9480cfd0a082b09cd8cf2b16a965d7a98eada182991e58b6e198237bb0dcf73f5e45a0bc30477a6aff8e957e4969e423399972574de0face0143aa609afd3655833ba02e3e58c2c5004e84a555627cca203db63229ab2ea74013b5a339508bb6be6175b96a2a9e3977546e22a7221a1484e0285da39ef40a2042545ed003dd2d657b2552d8aade9c19e220eaa0ea7e4c9c3631366015e736631d51c59ad5e1aeaf5bbc77a741dc6e71d9b2b76fbb68ca321e5948b4c804f7d2599ce99628b7b0f67028633ab86f26b118394509336e09a4257578eb954a51b009b2ae72aef20813f33f81ce4e0f057a379ed7ae94a5e8fb1bec12bf3467e060fa9a435f83b8cdc457c4dd4ee93361a42e35a3b20d2b067063dfba9d67663c637bda214c8ea5e275da3296a2b8249af8ac4e7240159ac57e8c6867789a640d60f24c055ee32e76bf0a86d17f7a8132ae6a180acfe5eda87a705edbc1726da5b1f03b190e5b66853fb4a710bc8625de508b7c31cb554031e5656af78e3077e8735377bbb110878d594a76b4d53e60a468fd490469efed9799d9042a54891e50a038b4811c8cac95b4b22c613620f2a5dc2c1b76ab04151d9b90b269643e98cc81232aacaee7a7d91e56ea5ef848203482d0057a2cdc09170ae1971f7a67e0b4e05973833ffff5209b0e82f32d599b0a5bee9a4c94976a845410b512cbc6c9ff2091c20180bcf25e35a422c9a0e037bb51de527f9189df8e0d6757d8ae2900b153ff5866a77cd9fe91edd431477a521da9a169c253cd8b32b050786a97fa9d5fd02147edc7c8dbf30937c59e786965f27bc52fa7608f924d51b169a2c374ac18221f847f94c84145aeeb3a5a2993515b2df1101888074e753b14b75bbc1a964702652e588fdfa26490e84d168e50ef85808644c02d1d5bb4a494b437f07fd2875370bebb48043fb6633613fe51308bf0bba8480d819aeda8397c6ab9cddaea58625e0bfce2dd0b2ebf77444b7dd21b166f4a072f67c20cfd19f5909abb4e1385017333bcc72bf76ab3770caf7f7b42eecdce3bd8dfbc477e4b421118689943b7001f2176d3e39aa91529475352f08e1b5bfb3b381ba741a4036735dcc76a0540b1dfe4612fff0be86e77064b75250bfa11c07071106f47438e8dcd714118ee8da25dd0fe796285fa23d113ab5b1a5593622031200c5209c91a2fd5a3887b49458348728a3e682f96e0c44fdcef5c5a1ec1646ce4a46bff44942db305b26f87fe802c88c5c00761fe10f0d91103851d91285e1fcc48d573a24ae00133df7c87e5203c122a59b59fb9a8d346aa363a377498e81a10380c7ededab940b129cc2599a327f1e2fb28df6e63803fbeb18960061c8b3e390056e83b3bb1f98153f591d241fec108552232d22e0268bcafb458bfa9c80694fa6d32caf23540db84b70074a3ca63eb8a0956c9a9c8b446519e8ae72646ce789458502201d8b264e4725e2201759e06510ac85bfda6ff1ef108e3974816477681e5a7611909e970211935dbf3e0a4a76f83719f284861b2125b3fe8a573f2ba9259cb75188d0c196395273551762ed183715e89ab1da065740d9f0296cac340865b999852ca3ca2ac3799d0901f93159463de983577c4a0a6c1cc3665be5aead9b5a56eec9fcc031e22611fd07ff39a6a5a86e4cbd7dbc70b4118380189c732365bcf6e0e94e0b5e2868583e3cfbc6752c6468bfec22833f6916af78cff5734dac861eed4465ff09e6972a110f54e3d7fa74212e6c6326e0dd7c311065a9bcb73270daded4b19837997a8719151342befcb42157359d7cf2d7c64e7f71e6deb91d9546c95b9c5426b64b9dba361e6f16739aece4535592a5f7012e478c8d5fc3339823246f6a2c1ef6fc4a451dcc600bcdb5074579c4bbf9b4a75977073bc2bc3f6b4222b045b2a074573263381ded12176a038764dc3692b56d215096f741d5445883ace89c5d48a86d570d0b0565e94efae1ad9e90ffcef46312a23ce60df283baea5546381134c3b46e822750e2e1863b504bb2d846bc8d3d6b7e00beb3efd4a3f02675bd8df4393d498e11df5a63ecd614b118d9ba06b1b9b4251b9a2bfc1229c2d8566383666f520f133b23bb8719d264a4cff9f4e5dcb3ac481d006d4e04b15a8f1950048682d4f2f11cd3baec55320fdec0bb41936d42b84537c488eca794acf89fb5399ff71f558d374c1aa816ffe2163cc99438f94e52b8aa020694d74260027ffccb45215aed6c23b0b10face9946ec5a9f44b869080f0e6aa046855d043f0cf200e3f55919a3d2b150aab398a2edb7a92a1333f7461384006108ac81da73e2b394e183a5de5753aa80c3a3a063f0b5bc04d5e95838e75f3c321d5f4bd94ab6ca53eaeafda0d0e2b9cf82afa335c214011ad10e64536990a0e9ef09a7d10da151dd193e1479af110aad8d08467fb6f5a1aaf8b7bd75eb6c413a2af67c156063ac4a1b2e83a3c1031cbb47e4b41f2e196df9fc2c3e8916d6570b0297f78dc1a4fae66d748f4a2ef22df3a35a5c164a6bb070a4e031768dafc9b134c06be86b32c2a3d423dc567162e1361360f768d725754e40554f35658f3f847781186b9f4d5379b7ea2ab1b29327c7251851f399731dc6a848cce62d46b50190edf2b605a97f6246bb393cb0024d7282e6a4a1f9322398a1196ff105ea45d31155a2b262215a47b8be5dc614333424ce0fcc15c12f9deda2101f9d64e7e6c63c0f85954c4c1a6c1cbf1793cc03afa2f2f1119b80ccc5441e3b2d42c70d0b531bc6417e41d1c8a33d88782bf230d5d2896ff3978787b075c4d1e5a173486d1c64caf3d38c0e24789481b22153a1869a59ad6fa7e484db5420c8c6d7d642c2efda9da6a6f8b53a914a732d8e51607bf9fac1ee94a51ac3393352cd6bdd2e6d87d46539ac1bee6fbc5cd5aa692aa141e3b772ef2327b5b0745cae21adbf360345ffdd3c4bb49b0a9f63e1403967d06b362b9d86fe6ac3711ffb638b34384e52ee734c6522f64a8804fbc97241c312db2c888de15a10e3dd908492fea882e98729e3009166330a08c7dd4d1043c9009a0c037f57d693857ef2e35965d9db9897884e2e560e4725b74b2399da5ff1e3a8e0aa6a8669ab21cf15c7a17e8a8c948f7124ce2a59b9c5c435f1894e84e8d096d54c343dbc3f1a93dac1635efc1e2d384ba34eabae9aa5b74ad85d99c3fc927a3e49996c5d3c592024cb2e1e2ee94f28d4b06ab9b3b0e91c22f4a689a12d033bd3ecce78c491d282e50435aa900cafdb1e6efa9279e3134e4d04d179e3c73287b9ba97ff3129b7211c6a971637abfe676b03c251095a4b0dd6104f1d8275706e4c9dcc849603e4dedf57d2f53d07cf693741f649b8f3b275ad85143f61a4031af21e71ee6e9f3370bc4d468441ae86fdbd0e8d73e831b287dd79f05f71599169c1dc9de69fa8ced777318054ca5238c479b90a85c979c03252e032717bf1a3b4ab05831517fcfe5ac9b445a90f67880930b413839e57d3fba907e600e68470a983e01e6687a354729121520b212139a7aafa839ed84655a2aabf5e0e5ffcd08cdfbe1f2c7b3554da640b9ec0f5aab58ad713dd5d591423ec6611480da512931e789f44bfc0e71962aff76e8aa54f7b040e4924fd5e3a8778846c847f96d34216bafbeefe630da34cf0b1961ff3c74c0bb1ae86ee30b2fff4e2454ed2d26152a40af05b9033cf650e3d081c4684b818a51189a2f5b637212dfface72a2ff222fd356405babd708a2ec07c14654381f5feae397c446bba7974a8355a754136a3f2054d9e672ca3b35c7fcc472ecedd7f8651495005747785a92a296a9516eb038a2e0bec14eba44480507500290bf2295fdddacdc6d48a6e9476ea7d02eeba3007d5362f832241a456114d73ad34520fe1bba120b0fee522b773898c02acb253eaa4012bcbf8267a8b9fab2fc442a1c05a0f502fdd47b2e4d5f30d280036f6e2666639d1a09050ccd28ea8aa5358829d6306fa0b9fa6e1fcaf84f633fbd130b2bebf77065ee9973f187d31f8ef4a0caeff9038482d578fcf0471361464431f12ef8242d34d04d6b8ec3db89efa88277feafc80fa8bd8cb7389a0036f6c7bc5b05561d08c6e1064c0c011d0d6e3df83f344cecdd96cc54eb0d3a53e8ce5e7ff50de48debf69419f8b49caff89f275909ca5debd22d1355e188d6833911e0614618b65e9d2b330df5ba9e05d74abc64fc90495c4f25259419b608592a401ef89a1992635b2efef2391723be4d22fcc958b8dd39b7fc52ebbdf664fb25317d71d100fb63a73ff88a494f5e0cec8e0a9e0eaef431d84c84f3ff1c9db769fa7829e6074365e302a7abbb0ece5a5a809e3a7e273b136ba61d5101c73054a81456c36e3aa009771d07f68ce69b86618f0a8d272402e86fa252530a2217cc54ea854b021a157927855455f48a078be880399c2f747e3d426ed72d1831eb4e29270dbb731cb52a5ea54ec24ab7f22476afc661ece8ac3d439ef6ea7019d64ccf3f2b5d243765ae1151faf24a38a1612f50a9521f8f95c59c4331a771210ecc5fa2964ab403770044f28e24dfbb9199a8dd6e9df21031a46e331ce8bda986cef2632cf8ba1bdf3aa35f65c0e191cb1c9defefef1961b8fd872cb6c0429c4a1b3ff4b5067f3fcd7645effc2aae880aa8397c10e4765fbc569b4ec46ed46ed125b5814bfd7d0834a7bd2f55554643a42aeee08e146a7ecd3904941a6ac53b37463cea1335cb0f27e8d394b12565b711c02ba475592365c2e4da0fc36d0a603b51a8afea77b8255c9b0ee939da5f12e356d5fd09d395be5cce7269410f4d3c0042fbc5d42a3b09036f490df6fda2c37dd3e4e9d0d0c2ce196fa54ddecfea7a2610d82935a14d12761b4fc179d02b77d57926751ef689bb7adc7bc2f953474766422b060651812fd184255f95936520780ab8628e3df04fbdaf1b942a97a40add627a067b0b3518e737cdfa971d591c21e0bfe2527a84bcb478eb64ce5a638b064ea3d330e12503893e03e4e82341f6c7d7b5cd00ee16b69c2c8e1b550403282470b1031147bb3fc7c170b9f89312697b74ccd542b0bde28c93918ff3e3fa8570e7e5813d4a3d2edcb713c228c56bfea01d7d05f3c687cd3163cb5bf4174503ec7465fb392d65171e7407a6f02c289f5298cabcc863ff958608a2f028f7f527e8ea40ddf5b80f33f196f49fc4c794f2990862e9512a0438b14998cf9765c5e4a355d24629df1d2d7ba0c4b5ca2fe901ef3a50d60e78107bf50ab5542853fbd44afa38a8142f4112b273645c50a87863d0bcfce4839de6ec6c19cea84d15dbcb1182d7391152461ca6704c98c8ac37641da8c3c73025ad5f7d20d60535b01017a70ab49e29b7e303fe832f612dd956eadfa031371ea4a9fa37534505c38ead226f2cf35638280928b9cf116dc98252ed5378c7f2ea02b25c2fc5cce6eb2a88d5bc886ba52eeb773743305eeb4e1cae343a20b393f23a780181477c5bb5c5b932d40f377c54bc0014a5812ea63025dc1bcbe209ee193c83f043b6f2fbd5b204fc2ef88f5f27b2b61d225ef1ee659a6c9ec7c544156042db52a4e5b9ed53db94595e67c002ac53342c687774e2861bc565fad9ed01aa9e775396d7348c3fe34fa3871e390f883a7e133992ae9424a1bf45c13d3bf21b9461a8af9b07d7ba3855f96f50560dc8d9530e88f44983f9b6f9faff82df9fb459024ad2ff45790fefa97e4cca6cd859978618174d626e6a60f36a2458c06cff830062f096f7af692655e53c6e324c7b44ea1dbaca7bf1a3b5e052473b2260b3f29f5f4c6dee4638c3e4447a8c6842b74b56291fb21aee77fc03b684ae21c497f041f932e71ac913f2348bd3e549b16e660207c75a420349043b38ff02c0c597a750d1977c3ba910f7b9e32c582a45b978782573a39ecc101b69ef50c66cf19cfe1e291acb96f38341c4f8544620ee9308853a36baf40b81871c0dfecf7130aeae8b812477321cc0fb3b86ed75d606bd399a24b2d57dd4a7d2a6a38cda7423007465c50f23e7c4e3e9cba309724666085cc229927853657b44851b620c7e84860342c6acc0e015d35a2c6528ccfad8e19b7506e546d451a55a9643c1c0ba044f7ad1a7b065ff7a1b19ff6be4bda3d0ccf02a371869e01036b7e8595ce952f6b8bfd3a8d1cd2faa8dcb2625d6321f7342e76c1f172d32f3a18d6f9ffa03d0a46dcf10eeeb100fcab0fe606d115b871fd8fe062de44148ef44b2e348df5d9b3fe376e722f4149c712cb4188aeef884deba1609223d17e6430d8053405deffbe31ba7bbcdb41c639e697d0dc8c707169c89d37a2a3ff3e3d24af05c77fcf331cfe4d672c513849db6bb7d883cfdfba30e2107543ddf71ab22df11d9b2c20b2e91acacfb1a10fb347d47d0e4841297795f8e2c2a008f25d5e451f1ad95db51813ae9afdd60c7fee5a2008b0ac1bdf9f73dc94b2824456bd0b03fc40e2723f42c165583233c1b8aaceb5f680cea8805508266f0c11c7c7dd3c9d2d860b1c4ec3baeea05b0e9a4a11f591f03ac389714b57f2c959528891bbe5ede91564a8708bba85fa699241e6cf5cf8fe7b34aa52f9708e5c01a2e32968d943f642212db6dd347deb924f65ee07094f9afe24e9c2cd330c45b572baffd8f94bc9450edc55ce499bb975b352bedb74ecffdf4c1770512dfa3ee9634ef6bf049714a524aa4254e6b716a07b5e8811e8ba3d2d07c3836fd826487dd35a81e381ca9df24691484bf8f0efcf111e2b0b5485a1429fc009730530e009c226da35c31f50c5f7e8f755e9c5dfbf3d406555eaa9b5adf552fea61f9f55fe60668b5790c605525622fedf626f2cd738d4492cbbcd41dc6b612d172d8955125232ad3620f9086d8138466d6e6e67b6584c2324b2c15f9c58f2dcdd576d8dd93a8c95e07633588b134f569411bf712610b342629acdd57ed42e6995138c4ae4c10bee10b4e72a73357120b9f40c42c522870a70092f841fe58b180d8f1521e3b021bb97c2fdc86566f263aa6fe3090d0a2cd1945a2de9344256445c9e07ddfc512e29fe6b801acac771e7e9907d1bcf81f5be9cbac995f5ddcc4a7d17bf8361221d821c5a8d49c75e8ca786531273ba820836afe3ea89628e53a265676d35dc30966b0eeca70c172ac6395658240cd64f71222c7f6cd740fc2400c23847a783824070f4a97b1e9dc39f393a4ae25954b57410b0d51182c35f5de719aa728c5f0046411e41f985fa72bfcfb585db0b4e2b9f5357a462c88837cc06c72464546ea0301a8ae027abca9348d1ee0003f365755b5cc4ca89ae5472884cd5645d90cbe87116b1cf33d24bc7ac9bd8b001867198672662616189135941ff810847ed379a4ccc1c3ab0b0a3e83f0f4d0a46aa576ad4438f19dce68e3efc01431ac63eb6f16332c35e53eb99a954d667a615f24ed9fe44f599528708a35dc3b9a074837270b0c8c54e7d348aed87e158f892566cbb4834d84daba95ec7d54d5dfbb77bb12a3398d96e115ec5b5d84a720468d1816965c47687d649c696e5939f7c3f52b301edc75cf71bc871539b90895f9e3c0b26ba5ffe7cac99af180863744331b5f748fdfd73c1cbc6f1f54483540c1bb7b0ec6b37dbacf1cb1fb5dba3dd7a29b3d802a4838b10fa3e93586f8e59814f78b8f87b5b3ebe2167be190d5ca0e29b15ced18c07a3c56f227508549d764793f5663d90836988020dbe12a6afd24fdc6d3892178bb5ad221510ff70e072c64449be4da9ea06c6a9f0821ab31328ae00e20da9bc7d813f0af1ce7908e8f41715418c4ca639cb0d1193d6fa8e6a03518f09032152ad7e8a24b96c06643e58583aade58f9f70457f340393ccd8f01faf04724d892f88cec5990f769e083d7913f1cb7a5211b6dd4cc46e55213064254bea436ba307706482b07976479f9fa9f63fe9715037b13f218dbdc7237a65d7b6c6dd2d8b200c79092af04ce6dbecc38e74963ff0824249705bd4922371fd38432fde1d53d8558596e403e799730b6890b07a126dc63482f697e45633ca7b7ff75f3d5bf30257abca7f244958e7d8379716b61001268486f0b591d8580005b8996373625865ad57801074ce753954ed4a72c2f1a39e6e5f31f83a91201af345c52412d498ce81e9a4d075e6861c6863b09756aa5cecd8b22675f9b247f15613e9b3444bc39f5a0b06c51c890e9a532acca95805e9759661daf82bd86d06e2e6f7e4ab47f262ee3b50e816cd18efb7e3ea2d0d0e094094d741de361362687d5967dc85b2e1f86c1c3e2949e15c7e291762d3394f69a17b6888f8021981cd11ce11b42082403c765edb73bbce4b0f7d9305cd24af969b03b11abf0d1898b835de54af8d2690dda321946e3cc8c47061b797abea11ca10f76555c2da9c85b009682651a88a02aa8a22f4a01b74826ae647f49f25a603164df05df91af107daf8916b7f3933d04574fbf9372f339dac6c2890a3e7a66b45ae3bf6a07053e5226fb4cc18ecabdb1c44d0ecddd30e70c2e10db3dff59a7ac0a6871f049b2f49f31e21f7df6c19b2acbc549b380277cab8ec3541c9e53d1338041c00bd178ad645a7f4f4ea32163b36f2e4830fd089ce565af73195564e9924bd180e15591dca85fcf0275ff335408 diff --git a/zebra-test/src/vectors/orchard-shielded-data-4.txt b/zebra-test/src/vectors/orchard-shielded-data-4.txt new file mode 100644 index 00000000000..7aae110de8f --- /dev/null +++ b/zebra-test/src/vectors/orchard-shielded-data-4.txt @@ -0,0 +1 @@ +040e32c513d3f56741e86d8fe325b4bbb582f74c9472ad525bbc5c7cd01ba6230959122b63f3cf0ce16af21d0338e542e2cae3ce5d8341bfb927abc35b3cc8fc1c42677ec5bb2a8b40daf549bbb48542ec46ce8df5c5f78d4c338b6d742c24cda774c9828fb31d05e7fa99dd26a2c9ea46298ea2fe9e92f2fa77a6138935e04d157f515a356c6eeb750fff0ca5126d7134373cc1cb0dac43476434630f687b8f10a6630239609e2e2ea63680a05ab93a1d94236acdb9c075c89c24d9807e77ea914a8fd67366d6c560630c532e6b9c55f61bef86bb9c3abc0d2b76f6ae0bf44532438e10ad83ec0af949a3850c147bee227b1c333c1cb7ae98789dfce93241c313a5f57c7eb2bd92b29dfb41fda873db912e79fc3f93cfd267899c4ace0fd0b3575120db7c646a814d6eeb846c61175a10f17862db7a336cc9016d0600260629dda20b76c4b457de6d346d1bf6521c048473d598b4fdabb1fa1c8c78bfe59da76ce5b5054d852ce0783f4a30ee926402143b825bc577e4401264da49f5ecf3350d75cc4d6c1ba977d8785fef46a42d03c2c37b45713c1f9ca0a59171293dca915dd8d6fe212080f6d3f9dc1af76725b4313f0eded66c104ce064c687fa80c9f43f321a059817f2004195889b1fa3ec05f6fceab3801d6ec70f5581629e9d3509258c6f4d61d5862907cb7400433a882868d3e118897b9137e690b6743f0e9317fa815ef9fcfea465ef8c42345147552f2e6fc2bc9b125114baef5781af818bf66b4f0ca700d1f43a9a122d9898acc905f7257680508a37eae3fad665d8cdb477d556e93adf03f0d26f2793d14a14b562c28259ac56e546088ed498c3e8795905284422b3dd9afbe900566c7ddd27bc15dc4fa47368ce7499e5950d0a5d65d398e97e10128bed6c875cc3121ff2a38abb3a11916aedce71c2aaffb7be3fefaaec4fc290e26b6af6c8f09452c5d17a84949c3f073ede163d5c16328763d2c79ba86a82f57d5222be9c1ef2610673bba8e2325dfa8c99b902552ccafde4f56d0a63a89bb9bb2dfc8834e13ba1e4ab333c819723b7018d2ba9b978d128cfd7bf17ca1b383c2729e17d7cd4b2b7e4f84af2fb2eb347bb4e6a92f859eb72054c9a33a26f50caeb14c4e6799e131f87620b297af145bf8c2c7cb85970313843edcea7c0da45fe14363e487709bf31b840865fff4b9d125ea9386d8929a91fc8396a5b957ba5d8c996c66384efb369e6c914f55f71c50e5d2bac84d279d3b07dc95c339c44e0c8381a3e839cf4553a749c00a14caf20c8b7bff12cf2d42f4f11c07eabda17c2e36c455e3ec61b8e5055bf5511805c1be16d1a692d38d25f60544b5efc5bd29b1de560e2c857921fd4f57f72d3d17c1126ab8be2e96976867eb3e24f828e1f7afbff8d601c1cad8bde847b722143401ea6afd519838251ee85ace5d327dce7460a8b1063d3db3016b0b8abaa979f57ff3b3e4c91a3292edd567ee35d8b3335865e3217b4b4179f8a0481e98102df1484b27cf36a8eede574c23375826985fc4eab71fde036bf086eae0f98c3fa21efc2bb4968ab4c87c417aa735dea256abfe5efbf0e862334449bb173581893602e3b740a52e48704f0bb8c562719baebd0ef54d2a9f40eafaab80233672e7f9e664396cf3a7cf6687959b9c3fcf2f6275997dce37ca836a1896d3264625e7c09e8e410032f3c22abed449f46979bbfe02aaaa94f191478341c8840a2d3049cbff0c72780cf3ceb9cab8bbbf1c2b422fb5ebbcdfff4fcd88d907956d42091fa4d98e23f29df1be49d16a79c9e53edb70f071a4af5b97ac98d2e10ae0511d567f672e353cf10c5c7ca80c8f23b555d18fb1450b5f19dcb2195388e7cd2bc1ab17717a376821f3005c53922c5bb452b467c74db5790531a5ca8cd818f3d6666853bdc43da0ebef77273748ed8a059ae109c5ca625672a60006038429d8759d43d33bc0994024633653d71ec09d8301e8c6e4f93663f729f4150baaebbc894ed2e23d13cb568aa02c83ccd78222619ac45ea6085cc0ef60874e2980439245d189e7b9d9125c454cd2117a363e4316ab72654f9348447d62db929a2e43a12ea1dc81ed537cf5e3b8a5cbcad0268780dc4796fc0782dee77ddf34e3fa9d96025438e1969190aeaeb0c53e7ad28d6aa1288dda94c1543b3668bcbf12c715b473f552abb94436a2395d211f1f6ec7bab26e38324af592aca0d0de2f3bda2bdd42ca1148919ad9ecdc3fce1ad8607677949d445a5b36c4abddf63b328f885461b6227e56baaca18220b872c2eb027f7910e4134f64dee894bc5bd1714fb4b7a1b0a70ff04d38afef289f2f0ff292b137d217c2ae85cc40664a7809fa583f1e7fcc27cda69d83d4709a25889cf29b7d248ebd4da15dd898acd4a90e4b237234f6164b1f199ad6d31e6776a28a619f69b8e32b85ace699bb00aa8d8eb5a9e3a4a3a45ea0949062810ebacf5747ef48b9376c1b61861264757f3d278a0340dec84c4c3e2f80ec6344c2863183cc3e7ec3e9a6900ef641aa7a04da79a8bd43f94a536bf5bcdb055cbe421b7265ee99ee2dc25a9a6385568471a6c2dc46485b5fb2114a4ee684f28f8a4c1f82ce8729f98ebfc3492bbc9770fb605b4a0502c8eb4517259e9d299c0f9498003811ec6afc3579c1e10e3f5ebfd2828fbc47e859eb0c47e1887dc70d050bd9fa9bae8b6a43f171fc393b8db9739e4b3e4a40e1f84d3f44cb06a684dfe9b87df46081c069f4d6da767fd0b203644bf07a81cb99d16ff456e95a152342af9d87594579a9372e013480e931202a6d15bb2ea43bf843c72f7c7350abf446f0cf51a88bb05d5ceed2b3359b0211c5367914593703aba7266d18556a3eaf074f8279e76171d61a7e59b068f9bd2b6c7a0a664224c7c3370efadf7b07b5b07dc9f3b2c3efd9da4a8c552c615ce712ec1cba58a7db4e8cef8f42ea98846ee454f098ef3ec9177de820813faef0ed37d7714521655362d745a26751375674f6cf7b98d0ee6cd4a50328214c22e1c8eb849cf9636338239e5f2e5a1089522bf79ce49c840b2097ecf73e49c8d69d03008f420b371be005b2362968426f7ad9229b9a0b0064839cfa099580a78dbc988757ca03f3eada8d13a8cc9dfe9e534076a43b86ca9a9c9e53736fe13e376386a2d139a69dc99055284c11681f7db86e9a1bb445d4e29caf55e4fbcf0461bba8c6eda7d9aaea0fe0d2ae05cdadb0f667482546c0d75f68de465672101f09c3ee179bbc55d2cb44f4112b432a4751946ca30813fff6eeb447b85a8a6eb25a83911e83786678b31e519bccb973a5d48ee7594be0f62a9e50d891e8fcefcd205d659c4b7132d92b73f98ab83fe77b4fc9000bf7d9faad8052ce6d86c05e82ecc8dfc1756d7a0ad57bb70649f97a1fb04e7afdd19ad65a130bf31278ac417f052b089240a2a5b57889df3c7583116979d3b92581e266216df025277522941ea5508444b7875ecc7cbc5035002b1505710f2e1c5859f1ef40d8811e88d06c56f92e44820e61cc5e091384ac2f159d809f60ff0c2b0d2f92a4b5278e5c7138cc83fbd0e3c41a2481cbc0a2e9bea6dd5d3031547f11dcb6abd3196c5c7e69feabb87ee9389b8e18565a22d89ef759422ef443a198cab949860ba28cb1bce12bd613475faa95f90357345d64ab971496319e4948b129c70d8b554eee23381ba08af2e97de6ae66e5a56e75dc48c55cd627fe7c41a9c95613e6fc4d9e02fde9b85ed2d3ec66a5bec27b664c79fe8cf40e261ef257cd88a6687b89123def41cf719ffcf5a6fe751861de83be45ee724af5e0b82f079d980251419e2f543e505626d1ed74d939ae50d7ea56912e185a415455285c9495e2548777bd270b30a7e4a411741892afcede6a87689417ad0d67fbb44175077c8016653a3d9e1544026a1280b08ff57058eeb30348789d02c2d40ea7bd67dbe3da22b7cba291449c409d24340a621909d09b069057444a4689598328c855e105bccc4be0d1c119a8c919a12ee2196e196d4f2aea3d6d0183a5b5c889af6ae15e9a4f2d33a2e392d25ed7732d08f901add5ff7974740242035edc8602471ee7e1294c4e2a5f9bea4a024debaa9997b75af6da00a6a9b7e0710bd61bb81eb2ba4f2fd4ab89814db6dbcfbbf57cdca05a8f4339eb1736ab9ed6bc01b0fbcd597fe54909279cbea79bafc97838f60758991926d8afdaebb060469b306f6be76962d2bb454559f364f38292ad8255147b5db99e5ec9a3b976e14d1cc2e7fe9c691d40ca158c79d7cbe92a0dbfbeddaf3df71fd4aa10a7a123ff2989727d245ebb95533c39e30195e96c9f846172a3dd80f878215eac5f38673267d3a4bb34611bb76b87c14a57fee266324ed75caa296aa60eb6a1a7a218088ee56ba0256e81a11717e8d83f2d8d50a14d54cb6775f47d28e58ecc77bb49e7b75720025b7414c2b4f690166593f14b746e4493135d18f0bc5c952f39eff5b6f6c169c3784afbbd4b8161ad6b68ff53b4ea27aec15d787fd5627b580699dfc1bc1fb7207194ac006b411859af9711701173964d1248f9da64863437c21b7e2801e59e8c761440e1cca71897a2f458cca38f57a938dfbb2adb589e69ff54572ef924642263999fa6041279a030a000000000000000000000000000000000000000000000000000000000000000000000000000000fd202eb63dfec183a50c9c75180faf17e9e20911576b03a0ee0fc937665d1b01994503dd99bf0f380cd6c7ecc3e0fededfd8730f3344603fe2b4342260f07c81a5549d7bd28865cd581a5adf8734e73c897701acfebc01d8a7818b56df106ae9ea89ad174612702e754c1a395f35fb8f186cbd7b47db60caaec4d54c40dda3df45e40f7a2aa7a2a3cecdf54546f146fc6f689b490e061357880c85677feeac3fa684396023e9c90ec49feea0929c592ce8d3accd68df3e96e47e587046108199914a3854869a77a326ca893ffa3a32b9b0b5021817dad59e40be7fd982208cf7bbf1bc0157ed8ec1bc318708bb4794646925e4137563a3f8b4d84b5a24ad4a871f980b76848eb27bd0b1a6e38856649fce015aaf86cbac4b3b89d7e8a4d43b11ab25b4f91ed8016e231314be8a2a5fe666321e1f270f2096c4d03c9d46bca3f1b559a158aac1ad31adee3798fc2e39cbd0df63a9a3b51e4d8cacc73f18ffa02f547822974613554b464280e7f79b868a346f3216b4853612084e4017fc2b05a61c240ce76dee4c5fb4d84fc499d0c9ad8e5e4a978ef95a43158ec0da98081bcd1b718ada3015f1aea46e93595b671a026e2ce8a3e03ca055d336fa40b8e0af8c83071314f23e9ee5594e66894cfdf70e56322f72edec8f1623e6e3283eb162fe91dd8e92209572353953c7b272a3b8de3173df4804c8ea30177846123cf27f9a572735d8c89fdb28bbbedfe1d95aa61309809961889013efeb50149f47545942b1639564ca5ad45a4034079de3f0941aea5d888075705318fc92e6e78498e964363c9c03a8198724348bcb5a82b3c4574e18db65bc41c13aac6537c3e92f4e44f5ae099be636d1fd1f48ee1e992121ede00177a9ebfcaac8563e0a52fb8b2abe4f130ac114662126b3ebaa670d3ac23ad26f4502726d693fdb38248cb8f80e736e10af8634dbe2dd124be56978970e21d6c0de423ac29490266dca1e58ee1c6924af3f5c2f0e55662ddac5071b6585fc17144e709ad771604e7349a40802569303cf9bae43457f12b8b89dbf10a137a05b65d0a1b7d29bb61c42dec987313a578a6d159e6aaa71b84ca07f0cd110072d8d172d201e73eb2edd3f291c9282c6b782839860590204236eb992b28065c0ec101e62a26e8d5863b7399f373575ab82d6c1bdaeb76893737e19ba32c5141983d02a57ea85be0bea7305de0a253cdef279510d587307f8f09bdaf8713bf7b991d4c010b84d820984b450ffc6fb91199ec09f3018f7723371ed87336ec3f4752765a4fdab9634d399193a9fbceaa73db74477ad6849a6ffcfafa4da0e44ad47342ed8b0e3e7c67a33f41425d2c594680b4ab70a574157b796df0f4ee6867f5043969feabdaa9c5f4b6a5360ee080bc12bc2bf8f7be4485b80d57d69de75871b76e6b7483ecb0d011cab69a87490d067780ff6339ceb136e62f8171adefabcaca912360d16dcca093f1aa9e73d1ede8765eb7e3987d9a65ea3b6aec6854c6c217ee179e96e6de3c294cfb7a7c0ae4fbad816cfbc6fe678529f0c8ce56b9d6978273afc0513eede2a8ef51f67ad4e11c981d4e80fc1d935f3cb4d006031f3c3949c1b69c921beb63bd5b78942e9aa7d105222b7868f4f0b2d940b5f7ef9261773b551e0df7a901927903a7398392bf792831c382be51fb37cb86278229fbabbff595685f9c3fcd384a3ddb6c83f526088c6abd62cf1782aa95eb5d60bebee7609ade4c4dfa0a6d40bd3d9a011c89e8e15a0af5733a2b1a1c7710c1564aafeedeb706ccc687c580bc48324fa5809bd390115e59f19e1de04e22c95f0e9b08a02f09cb8e112d3b87767e4a3b508a816b90a7df89e2b4231da0976a0b16ed9eb7892b2d33e12f81c2d87299fa390927d4166a86eca1961804c6304d610523402b8b2eeedd192f1f9664197db0f8a21fa02303133903a85c1881f6c05626332a0384991911650e320fd7df6c03ab87a362971554bef845b46a9019f43954c95eba01c3d03ac752fa0a8c0edab3f7aeda127cbd9d4290db26ca93afff5c4a84cd5d8d770a4c7447e1fbd8c7fad24ae9fa70288ce738ca5e93e485d61a863587dbf22e7f041af47cf7cc528e520d225ed0295509e28143f1cc3f80a78ae6dea1980b9c875677cdf369ca0a12874560db66f3d49bbadca3f365eff547293c22aee211507f6ff0a86ce8b5b0b588cc966a87c46add27cce861a7f5889849755cc84f846bc51bdcd470b1cfedf870a254783b24cac2325908131a2d84969b929c0ab6b77e5576da8dc3d1ecae2e35307caebf8f61282707a3d1f390015ecec1870d5c22025bdad46220e7ca4ab5be6cc42445bc00dee66b61903718e4e507e707197588fc62fb7b6fa10165ff643856e80eef440bef4363180e48c6fec40eeb1208b8a8a5eff0fd481f6f3974b82e71de0143971f67df93f8b78120793072698df27f97757a56a1a557d917eaf66207b559afe84c9c51e0aa6aace2b8fe9d0e476f8229e08af586625e3b40377151fbac5517cdc21d306ad23cd31033b1182a15ea7d4dcd2a12692211659d16973b548db33fa972c9ffdffbfc15ccd223ceb61eb120cd50c1d38d11b36331c811787fbb7aff3b7850ecdfe32503c5a2f6427c2d0ed8b6a50f91563c5b7d2a44723ed140844f77945a25e618dbe89e47ed3bedc8aba16158befd4c8e47eb86d0d0d13542a86198c1acf2b422cb275242905a037a87cde133ef6ef8a81dfdbc0d8f623da648a3ea9b84fe59f032119022801d712f3123d2977bb2f47d49300c1e9843003a1604e243de5fdb33c54a99f823a1ded91285c4df69840cd541958c53e85e376e7f5ab15517fade002926457e2373d6c54fc2f573b561e5a7e3557d52272c896a6dbfbfad9afd4ec177356df8f55b5673bf35c59c465d1a17bf09c0cf26c004a06045a80b139ac2b8e87fe162dd553a0fe9763c2f55c2eb6a65d672474c51d4677168c8066c3ff618af2becdf7263f4aa346440bb0445023ce7b62be54cd29f99e2c287cf553b92000c73d9227aa0be070f36a5ac52ea9db839bd7051a9ee570e705320a60ee4fc43737dc062a5342c756c0f8a258d7ad8b56337d60d00bf09976bfe1b844ea7734be0b19ff4031721f6a5683e82f2b1cca7b2c9f80a306666ff3b8b5f6601e316b084c59942a0d87de8e4493def573aa4de1d7c4584e65a4a18c1cd4c9f3b251bbad9f9bacd0c6f848d76904416c4486689bbfd4f96c292e8971055808e2c2ce418b279c9c254fc14218abf1ed9ea45b6afdc703564541ce39f1cd9b0db2f70a289f01aa3037f0266fb4138560d43ed639022f25b36c459280224eedb62fb4a188285f3a2c23fc0aa1a2203d2e3ae31aba052c8652d2e50401d0b3b2e92adc2f5bad5fdd9226915b1c5e635951b965dfb1c8968d4fadb6ceac690642a2e94b42c6af61c7466fe0308a52d24e8a52882cd1b8cfbf16be166d4118591c25984138710c623855744443adcbd2777175c3cee08cd3e0b39c4d7b8434bc17127a50c7f6ab80e661ec29e86150c9bf69cd2ed1ec7515cb0f3421c83d7c90f9a952a236701c4143aefe94e015a2f3dff29ab4fb4befdca4cdb925058eb5497483317f2050becf4b74c97ec0bf14f7da953844b245d38d6600ef977e6c049f318c25f348511751e3e28499b7a0448dbef7980383c5972957e2b9101e9ad54930bb32a7eb108fd5520bf9422a03138f23ca8522f6983ac9fdefd5ded8c6829db0f197160f8606b6a2107fa76e0b29599d7d94b1b509ddb3f2bcb49850635fdb9c64fdff6e048361c0a9b3e3080138009f30a7f7ae18a3470ee8e339dfb8b5dac5d13915d8952044824708b2db0363d932e0836846621429913b813468de56bcd4bc987b0833ab6daa14c8b06eb56aad8658339b45885840219351fea5d38806049fb62e237dae8558e4841e222828f4e5df23d2839c24461adc19d169f4828dd305d85f17ea3d58adaeba929dff265f3e4bf519909f4ca8bd4b92ba4e4b60dcfd62d20b13d8b2b5e62b9e5321841d9874c911573502a0c178c637aa977da32de32ec2e18d0f236f755d0f4422f5bf195bc7f3b19b9bf44f634b6c5661af900cbfafccbd29f821b7ff49c4508a7afe3443ee3f53a80033afbeca6d32cf7fa5f470c6aee4e6dba11401d914dc7de3a6db390e01e74fcec11f716c20c4d8ff0d6bb68171b9b9481fa0969050e82cd9ef608d22397677c066045515c63e76db560540471bf5e3d7b9611489065714f5d50a042cbcf06cba6f89281bfea0984a5ea54dc8db95cfc49c815864b375d732d539c18c4c1f3830fa6b4dba788951489bacb1721f765b6b046c42e4ec71dbb67b3d093ebd0b40102ada833d2d34fdc0e5539a95f843bd2fbc98a8c26248a843ecac0e58a42ea82763b797addfc67473bde0b9c0608307580bb6fffd68cb7a0591777e07c0812b302a7a6d7c77cd3133f5ee8f0811a1dbfa14cd8051bc14478ee298893e9c0a437775f34d0f9aec94381054135a17d752bd235966c682a50ba322ca5da452b613e174bb5010c6b95eb0f12c9560522c2b1a24343c2eb8c3323624c2e5637cebc28a3010f709fd468b6c6ed74f6bbbf5522b017ef3dc9ebd1c1ad8cc07df3bf080fee215c91b7c1e30b86fe335e2f501712b23e3d69ba72cd110bb81d3442c9d7b52638e51d3bada35fb5a02ed65c70ec6aa3161d52338af841560d919ffdb31a86373f0c8a31e46d9ff8063036f5036da590efca7b01a6f386e3b53d708027b8d0225e951f1cb03c4098131ef76e676f7d635c165143aca381954feeb29e0e78bd597625b0aee48fe7fd938116085ccee890478fc0540a257f3a4208e89f82946f7974ebc50161ef1cd7479466ae09fcc690009904055502766f0a887ff26b9f1fce93d7486997eebac3baa9d5fa46a9cf51d58ff61bcafd16e6cc94ef19b02631986cecacd1fc2d42b726e0d478d4df775220cc6d768dd86e415e8f22a9d996b9d7cbe01554943d96bb68398a79f6f65901e9f79437d285535f25950ba0dd2d5f1ea73ea2b061e97fc52b2dc9195812a5d2798f0580b28e99ddabc874fb3eca46291cea4ddc0445138a55d13d0a69ecf2e1a5b7c59d15a89d9f19a582cbc71291247145c5ca1f6acde0432c587ca56817f3b9ee9fc23b2c548d79a462dddbeca7432ef50032b3faf863d57968d87b298c31986646188d02dcaf62d958b4d178cad0d17d87a01ef08349510f3e7ca085269253aba020cf46ab6ae83f16cfc9ce4d9800d44667ab75abfda1bf747866daf70326b464da381d056f7be2ea09cfa6464998483f64fc6e51cf64455f66ecc787a09d8f8d427716b4ea211915114517015712a066b8efaae1b0efa9590580e95462b496d561a2c39585873f1327272895bf5fc7866bff8622944e7e5eccb79b5ed002a82c9ad0201b1fb3899503b1f0f0cab2a0b1dadf620c7de86b9d0ce6f28bd28570deadb100a4630be42f8540de8074d12a2273bdba05d558f76359c36237f051de216eaf2465a2cd1ea134eed0715552ad618bcbc8e32c2da8780afc07bad14ae50f9e047905f0b5c214fe2127679a3577a03776dd6ac8e627244aed735121987e2332ba11b8865b63a92b63330881d6f721cf05698375e7e20496a18acf701cac9822ed7a70f46f8e1ea671e16aea1946c88efdb7421c36c10202b8a0ff62fc174d03ca125235ba119fdd186cd1afd00cf3d4f21c7523771bf0b285e33a81f026f32a19b80d65e7c024e6a47c3ca9269d1d7f6cd08c8a6d0fc30fe0e5e7e2dd6562306982399a56ce3f5561ed0aa369e024ff5ed0784ab0f07ec45c89a982709d461016bcefb4209d51c439dc9eb17516bde8bbfe716babc7ec90fbe2a7a0ffb9e4cc2b391ed013bcde71f97d626cbfca3e902520408c938d97b1d2404731135117a3d02f5d33255880ad9de456bb0721ffa1f45556e50240f0067a89da21cb0780f7b9639e0f5de544c479084df126d223b0182f95fc4f59c0713a6e8763300c95af3219fa52e2df46a44d45e267d2eed491f8ed5d67113f7f749c7a4622f14745c70139a0f6345251f266c42fccd4276dfd2be05d61e49c70745af080e05beb6754db01c38fc3785c850e7ec92943af78460f6f1480f5bc7e649d934a606f4a08f852c858bf1dbfee64ad1412951093a611456afa4da6f1fb556feeaa43ba6c8eb771858f37c5cc8c88f13b0827580e606926c7a7ac9a6a384f803c21709db347dbbffd36142311e1f83d2a4d8feb18026473f791fe3bd7ed031ab1ec61eafd8babebe1e1609a6ee16c03c8d07e80c79bec581572023492283170580153fcaef6dd1ea936ac1a321cf1d2bff16a6420c89dbdb3889e1573dc0854dcddb3dfa33e4d5b391ab13adec624b61f85c1aa2a7edddbcaf1845d8114ab6e882e331cd2481d0d8a9b810346eb82a49dbe7a7cdd15db5f4040932e91ed4d17c3ab609e4d181982a36cfef50f7211364a524495449cb88eb241453d36b5d8564395101e2b99bd6230e9b08f3d093e50405e1d1232297e913ae316d01e6eb07547d613858f92b85b9145926275eeb8f1d2300d44f326f62fe2eaff4b27a6875b50c41008ed13994778530d50a5cba7ab0e211ff396609ed32b7310fa9fb2c4f4b3eed3d08f28bd195db0b29ed0ede8c8e3454b75222cb90c42ed118f8be3c36e71e5f1e9083c393ab85d1f2ce45f86a15a1ef7d11cbafcdd4c9d9360da2856a87a8e606178515264de193ea9b59072b3cad3602d68ed62cdb43944e3e3305d9f39ea01bcb52969a41daca3ab6f49b7a06763a4d50ef7f2054ed850d1cc4deaf8bdf982d896f51b901491f11a23d1b615d541a8ca05c7b91e23db585d87f990d0ce41003995802e183a467d5534b72948b6accc8143831ecbf35dc72144f197cffbf860c020e1355b659e92f85aef876e21fc912203d219a662785c3c38379db19a52a167056eb6b8a6bb944db2d6d6cc4093574ff7a5c6419afeef65a9d56c1ec76cc17906ca2cf2184879369af06afad3502c6f2221b235c55f8073fba23e7391da837d4318725fe1a378cb7b26225d521230de077e8f9e8059184ae63f3c1ded8cc1f32c4b9c9018e4f4fbb7a6058fc7acf2b770a6fb82a34943e402b9985961f4b0489360ae58c6bc66fd7344d1463e6a22a7f07120b322e63d9068bf3779dcabc0373f33c5d68aa0569eaea14a7ef3b3d5aea730514b8ef8b0f0a9da3721e0880286bff7b5c5f51d7b60c932adfbb959e921ca3fddfd5088c7887c21f6e6ac11920d360445e0fefc5cab84f37e22a76e506e59b0c52f5f11d61fd2d2dac4a51eb1c6ad78e6619ed4be91b3e71b6728f716e4529952e32c0a8863a5e872894b0a72d4b620bd26994c6aa81ca88bb4d531d086ebc478c64f94cff026d9c3a830b6906dd75d3ac050224a8992e4d3f4372ddcc3da62b82260012a38dbfdab44bc1f21bf794c23284862726ec90de07ae8001952e1fbd2dea27fa204178c97986a45723b61cc6795e67b751470f9d89efd7a3ff9886f6dfcaf2b22c5aed0a646c44b918095820f5e296f365f9d13a1c35fe7d289129f3d6b5a3c4fcf971d44a0b1e28297f205db1614976b99ac524eb51c6bd4abd528055ca23a91cde15f74595e7a330e8bfc3ced0adb8134e207ded569985676354f14aab0067e0d8b712642dc97b1af2b12c5a5f7129fd2962df3ce5c0c057d2d45bbc9dbf41fd955858d7aaeeb00eb22e50c3d63e6124f589082cd974e2d22df68fe0421f5440e363931816d69f14c219c0a05316a236f487307ce30fc063283acc9a5b01df16a80b697813b18f3fc66dbbb2f13ab28806d91391bcf6d002d94d596c640896b2f1340a26496fc20ab83bc51f1a425d14ff55d06cd4324ef950301708ab7ec9d2c80bc0435be27b308e281827b687545d0419426bd6969e4d024c2a6073d8e67569790fdd274ea311435b8dd4a0e386684611d369e78046f4b330527a46261201aa49e18ae785c10410f9a61146e0976c5fc1527acf626caacbea942a6801fbb51627a3f1500dae2b7571c19c5fc71113b11c44a556d621f56b6c996d357cd1a6e9d6a9eac6841e0c6fa4095bedea316c8c0a5c52058dd432997663a06857827ffe0e7144dc6bc83c8af917d5127839dcd4f096b365b0f4df8ed0e756adc2c1947cbb859ec90d2a383d7a1a53c8146430a00d5434902cc7e25c62095934eff4c4eb334c04651d89175affe2db7c178255f8896b2cac084437a9494fdcdbfb8ad8a5d4e8d1a63dd431fe40fb97871ccb86d01fdc678862fa54455bd7dc641c3a03b8aa1aae7b0b4e3f4bc4c09d34b863ff97da05f1cf1b875a182e7ff7d08efe7366306450401cf7178d52264de482e6d39c8078ccc68ffb1fd0e29c3d36f91f1f97256860d0ad36067489be6e5330fbcd01a6ea2027c4608ce6816f5eba53f5c7aeac5229acf9552daccf547fcdc7883fb9f1ef2f9a770c7a972d32283ce0c11e8316cc6c7ecb8535e3917883f426a473a84c19468468c720cbe1b99dad19c41ea8ef8372becc9530ba98cad2146b4e3ca6d36fd41b908c34ae59215ada6d200faf344ff3e3ec0d22475d29cad8557ec9536e0c0195c85919db76e373d5d141be17e0ec81beea3a15a2fdb4552bd55e604a7dbb37eaf79e8938614e216dae5a464c99faf71ed6dd3d5d42baa14a47dd061669fbb6f4b45cad8ec068102824c813c7b52c920f521d05ec11b201505a40021fa66943d309830257680ba8fd9583c180ce28318dc21c1c0c8cc2cc861b47a4e84b6efb50211dc37c24a300cfc3606e06f5baa746084b13be9f4753af7d5dc733fa93adf849d2bbdba833127e384d9cef6a4dc2637e0d28633397fc56416d19a82a8d0eeecd7f351350b829c2be878b47ec041c248e4f14f1b9e072f5eb40570a388f7cc0aaa8da5208a401022c16c565bf8fef7ecc382002ce94e16cfacb4d01fc87905066f6a44b1c0c3da6c06fd799b80c05207e303593987b293edeb50ed4459492a52bf8e29b3506feb8304294c1c871e18e8a261542a77c591ab99f8a533834ea476173ead259c8765b7aa2e86770492f9896913e15ec824e1642367f2bcb89744192740c1f8a1a2d88264de051fde21ecb1a800308b479c8cd73b1d02f3ab5f5823332f5578b039d524529baa4dcb5185760051e4a12b6694a9b1d2e15a772a066624d5769533ac8891b9ce3e83f25371de08a31ee61fac1b6af29019838264acea5999151cca884b9a465a162920968d1d571134d0d6987dc09ab4a897c95aa9323633e64fb58c1ebd554463897b239e7f17e0c4a0bc7b4e1fa7652adb0125401b983cadb90767f575d8e5797963077a2537f170de05ed2dd6d1bc0749c5bf2ef205f08fc5e485301fc5f46363131d399e08017a91ea926a253779468f07fcd39b709ed68c6a26fdf19e8b86ac994b19198cf39b21c661124a6e1e492b98f71d13ee86dd51e90ccd9871aa7673d2f9b4a3acf067c1eb0ea5ef6f37bd0c3d6900a775a6154d8ad4b70e29e13074e26acb74c2d09ec4b29447f2cd80f85717ac1a3d47af8692db9a57b88d4661f4b544c9155932dabae26028fe08fa7b93bf14725e5ea8a21a735cc71241a28b0228a7cad66322a93cc631feeacff14e3d3cc70d123bf24fd2cafcfced3a2f1f0eb80d9a5953110cb3ad0e7a93b4f7eeaac7ee1e27d3dedf1ccdac4c7e0f8d010f4df53f26c35173cebe15c5c0c24e475a0a5f9f069a6ee450753f105e59b07bed71a29e3a54f2f2f992f309b8aa9b82c2bb973214f27ba8cc73c85b63e94195ecd2f50afe90c1424d3f9592c296fa8988a6ea14c2ba073db99e72ebe351d994a85211a2c20012ede5d45d66845c9a167dc6814e6ce147a3428f8a304eece7a2e5211fb048abc2e6a409be22c5e75f044f8e8594e21d00a22b91c3279e5720d3438f908d7905d17edc95088bc7bba87cebc7519f2982bef7c5ed8a44849f31b61588e12b6ac012d6820dfcdede5f0958c9cae6494538c14e51cce8c3d08b0e0d5af90a193878b12b6b789d6069106d0e439decdeb48657ae86f124051760ce1b7f27f14b7d5bf1bd2e170b2a390ceceec33c7009f289e8975218c4852f3e0909fd6806fb96fe223cfc21dc7710cccd45fd64f669985e34ac756eccd48e5a12169b30cd7b9f90b2c9bfaecc0f327b857ca2a6c6c1b1e9d59be7b211a5913a29e39af2481b169d1368253814d4476cdc2c007680080c4246f1b3b8008e1e00ec6ad21837fee935e3f619fd0c3c5ae7b03968b2da0c6af35a96f5b4b0373a4548d4cefadce47f7f43b98bbd02cd7b7f460359fb47082d1ba1b2cac02ea5e9082a95f9ed9523bd5822f478cf81bdcbb3b6c0b7f61dd24548d69df9575e625a7f7070cd32d1c76a40e2239f62ee5c890ff634837187637a9a604d087fddc0830233cf8cc94aa1e3da62717c70ebb05a8f92b11022e551962e7faedc38725493fda7ee4d04aa982b173221199dc54666b8cd574b529fc26d3fc3e8c07d0a8fe9c6d294b59dce0c4c5dd0faa23f64de1640f6efcc62c3f308d8836aa87041f07787d334fd22f60c38e8b28df7c6cf12a0eaa4c5d59fee6ecb9e99f7843927cf40d48efc205f739f3c00f2319ec51d4f7b1082da35b627292520ffd8bb1f8810add8f020e30e62ea5431d3f3ffa0990eb8a0e11c4c276b13a5c3152b70427b711710f950f10499ae40be4106e6234b4934be15a66f6d4b609e87eae0e9dc864cda9d9f94d908a554859a31b2267c8bddd35acfc1442f5c94e7709e78f3a1e37ee31df095b4f13ff5fd77a388955d81a4302becafcbeea78604cb5bfb26e11a5f07a05a196e2ac64ed3b6e2643ac05ed670d3161a42c3369d68eacc361d6075b4e5f5a0850bb96ea7837ef2df6719b43add6c1cc2e36cee3e52a52e70f8a3388629204dbf0366dedc3e41504ea29c0c1733f92c9bbb613e1337514499a7b2a5e6923e446f09b4806fed41b27f64ae2d4cdc31650880fb4880718df813109714f1b2ee3e09342d688e707d50172dfa54f84f186e88441766c79c3892927c091293bc53647c32fea8ca8ff021c67826d6febc93f1919cedee4982c2b540f510fd35f517a95b93f6300d004a120d1002254fdb8588b10d934a887fdd976425ef5d9f207d15c69083577414fdf316e804d777d8c56a017aa18e835c4d93b62b5df579adf65f04206f409e6b1491a8ae0c29233a62e95edb8177d9bb209eb9b05715b0f8cf82bd83d109c4601dd25358408688adcc44acbb2bc9c5b18157d4b85d1e60e31a1cdd8accb77e652001baa818d5ea6656ea54699804fbe90cc19f7efb96b2770235cc882b08ed96ef13b12696c499631ff0b5f4cea5a8ba9142cde40a216b7ae9a5bf31798d95a97d30cd9b4ae986d4fd5f5ab2b1699c3c000f2fef990b85c7a132d41a71608b04c7525457e20c2b007748102619bd32e60648c365692fa5c00a5ab4f8d67784b8cdb1a94b7e696a505249a691304a4d3ee851ca9468323d43777afc43bf3390be18c1f53bec28493a373ece4956feb5166222a6cbe715474e4d554319022a7824a7810b3ae8b9512252d59bcf131ee4964090275d9112ddb2f328dad33d28ad1089b0327c8b6686d851a00cd63c6de57e08104c43611f4c7cf3ec035a994f0ac258b312b16d53b8adf090eb14b9705d8a3b2a9f92f3e151afec5b41f9e6a43d4814738abf020d2edc2ac7e2fbab2cfc16e7257f480e2dcb3711addab789f0345d6163bb6a9b4d88beebdff4e853ea7570f2cdda9bbfa96b4743e71aff211a8144ec213c5a06ccf0f6552cb199d9d72825aec07be02df9ac20562c4855b9c851d99743295d06d76c64f3be1d36a0b950e2aa40b5cfa9eb5ae641abab3adbe29bddabc08c2f7849011ab54a66913a320faedba0d40a855738938394e8640cb095dbac128149e94bb14d47384ad413c57a1ad130eb7277070444998db560075354fec2a2b59baadb7e8f6ced51d8810b75d225972b01554e269c71e7f3207ab7fe5281827aae384f06f30b8992ea6a213535e4d8aa0d9cb0feeaae1ef1b42d7accb54bb39383ef3a2abac6d7b9f4bd3f7e87566b08846778355aca4dce0245fc56c426416b5e676a67c5e671835e7ec754b334fe6a850512bf3b48b88fb6479f681bec4257d0f274bc397bfa578b04f91d6b93fcfb81186cdbd2f39915cd4d4c7ec891e16689d7e087a4dd55b00dc1798e0387c82aca8576e81946630bdc88669bd3ef123572437c67ce255a22bfb58d00e058a7ea0cd44f84231b218d3cb008ee0aebf06978de497a69043083f7815c34de27f0fd871cd14499bd49f8d12573410576021599be9ddca83d37938a8f9155f852ba60e49995de099ede5b354f41921a3ac13afe1d868e125de195e561c341bd6976f9f946507c58e41cd6f01b7b8f631ae3ea8bd269ebaab237d5f77d034a4ca82668f2148ca0dae40aeaffc0a0791b61d0e63f8225c6c22128f265fb7e4895d0330c9ab1d3a5d5fd143dbe57cb8a3c8a92212314a21f01cf6fc2d17ecdb1318f1027fb29374dcb0c525f26ccb3387661736bb724e8c4d3dce24f5f8295a4503dca6995d3eaf732cc238553bf2b5796ba20e4bfa912625e0f1621d11bda653aaee277ce8b578ce1843c4ed1cfe05d111c008ffc2f8d38997c11b92bb07d8e4851994490ffb3de4ef41dd16843b0a656c0128d22e23b2e1d493da1ea1b96074d30946eca6a1fe22676f305aca3684a93521025bd17c72b6449b58a883169c8dacaa743c128303ae008caa66ad9c8b2b05ea003f534fa8b3ccc8691d5b0db04f03976b564d10868dc47404658e0e1329f1b6373948ba36a84e3ed19ac331ff5803b84cad3c4e45bb72805a68de33288860b621c17ba220182186aa6b822231fbb5795e906623b5165ebcad26ce7cdbf00a38175a976a22f5743c5d7161183461c295779b9783225a57b07d844707890799462b97046c6008cc0e33ded838f3cd1e87bed2c8918788cd84a297db8aff4c17df13e36bdc686595a58b19d9ad8d55e24d423da1a2a566656f25087c41e03221bf1ae651a1b47561ec91df0d83b36b39bc5b1c285de0d3f6b070dfa621c82d4b66097eaad6a3ce6392af0fd36d7afae62b7d2796b2da5bc057713919e3761575a62bca2220b04c7fad678416131f00128561ea99385ee6c9f0b729a99c760deff928fc4d15e313cc5a2ee7824c201714581864c250f4844ddd6e5a651ec66087e30af5db13882ebbf22f58d19acb644bd9074ef042d9138a8a564c2ff9a366a3031bcbf810e257b722e7b5c8d5314264dd621d7d00865d2db7ed4e5ae49968b08b331af576517b8c13dff72b0cf7d0b189af5842c378c2ca970c273e87c1334dca16787c5fb6d06129d2d6cfa7c1f84ad3eca89abb1cd787a079e99ddaebfcd65b30bd58dbe850ec71abdbdab4e0e859b84bd7d0477cc1bf8ad3704f767816a9390df0c99c35c93586c0dc19f9ad4e23982b0cba3480cf26fe2b9191362f9b0f8606f66822e0a1170cb1b0b78c1634294ea40e9941598db24d479cfc0338daad430a772f68ee90b51354315989c992cd8155095b57f7f74df5459eeba72088e67834c8d22577ee9d0abbb26fe5273c9a6883e77b8cd35e8e536c963dfd1ee91856097ed33c63bacf35a92143fd3ffbe3476152bed910ada62e535ced099d367c87162c8dc6a3b01d6e28e48e6241ff6004b71f894530edb9e0ce7b2d50be680ed73d89ec0c87a331f203e19420a6e1adbd3e5fac03cfc853ba5e40fee961d45fe729b8be4cba60e3d715c4a44845b264c503fc9661d2fc75f01ac79a59138c7b552f8595a7d4edc8cbbc545b98cf7107e7ae597859e18524156d21d6b4dca2afa30dfbdd64f57d5df3ba28342d3a259ad7710cce77a291116aff13aaea82ee171c043ba73a3738e6e7958ffc59eee906885ccbfa2c45c5457afd50d0395f319ff439d91d83db97c44dccefbbd42502cc6a12f8d8cf6f7b27966914b7016870937b063a19f35b73f8655171a315d67a45122efb3dbdd17bff43dc52b14b0fa0d33a3d18df5f3bdeca05153ca1b0fb3d24eadf10d4f01949565b5792a79c823d6714293752a262f5263661971293ddbe6b939c672db5403497f21cede130bc1ac49007f1606a13233347d9108562c1c4e81b96b91e0caf4a4909a1acabedb394430a07fb00650559b3f5b7d213dd137fa0e95c936c315cc6101a0902c46b9c03171507dc334a856c5280a37ae6e024bfa7ef172261c85b335d561c9f56610cc2a6b90fa28d8735b9693b802615c69afa433a3067a05a979ac8fad685bcdfd41087263e97603e0a9cbbf609fa93c64c1a8df03cb9b23663cefd5a06913b2cd6a0999f1bc69b07368788e28e38dd2693f99d5a038ee6ca4e7127dfe334daee14d131122fa831180b15431a05667ffd2e834a895b8dfb90a790f840a3219f303eecd61b01eec639fe25581c58f477f1f6ec75da03cb31f2e3d5dad317322ac6922e4d883ae118155713a2f1bd0770e4f1ebe1431c9d7eb93260eb6a50470fbac26f58ed1ede6ce99173087a40031472eb9146a4033d8856190dea3edc885b536d9c649e3e2cbc0af7d06dd14d3014b3602a5e890d946c0fc3cd5ce3b1a30fac4341491a320a5bd3cf934df7f741753720b2836910695dd1629badcddb58d8ef1a6f422f1ed33f504a2141b1b4330d765193bc40147cdd356d4212e361e6fd63ef62ed9211a7267e65ac94b34bc6365d53463be512a5cec33115d1e5a90fce35d065a3910a5efc0559d06733b13c714124de0b43e455f35dff7dbe3695d8e70dd04c82db0717fd7c7c58c2a1c91335c11a447a9cbdaaaea480802cfd3717f102a5b1f511282b9704ae993afc64b064c7d2ca329931ff82319dbcf5b02853ef0acade36d60383a1bff89ade83b5e7bc8b9f81d1ba8ec9fc738d1c80c9a97095557a85a97b3d10df435681332a4f401be8eb673709e88e0aed39b5437a78817c64f6358ae03053ed49955a842e6397503b7df4e49469b00d2d6da499e951f78aec8f2d06ad0ac3172e512f6b4c37b4e803e5d2f86aeb3fd7549665b5ed5ab6b1ec00f0899424c18ba1264003f79bdc99c1b110a6cedb9f3aa259e731513d0e5d43a053410318f224c6cbd9d9e97c9c316d52506203d21ed9d99d2b2578199bd8d594fc0aed00f253b0244376d22ffa00ec2275e72432ff752d4d0557c08e8d47162442d5e9048884f6f680355d90479720caa12b472e0bbb41e4d79ab66995bcebf619ac863abf8012c001afbbb7ed4c05315ec6f805447bc68dc15ec6b9152035043b9a1ea4fb05ad5bcd325d9f41f482777d700615681ef3c09157cf42ad19a5cc73386b15d9b5e12626608f1fcf48905d8bd924549e2b564a4ef4f7dd74aa10d2d16423062fdeb75f9cbd5ea5293988dba5924a541f1851a35bad00090481a7237d6da8007afc2fb3770de1748870f511524e4d9e45eef07d774d2bb247124c258d3633046e964ae198bc517a6199d3d85a860e31239bd6d719cb6c40a434e2900902cb3bffe004c4d0128d637162975d8c381274c142493c6c81e0b51452b95839ca89b401a66d7f5c51ff0fafc11cbe2a4db5f146d3e1324be67b72c52f22d6850b48328ecc6481fbaae986537922e09aaee1cb66e4c2d5c3fa9f35bfa7995c8ccb53bd6a37958343fb8e26ee0f41aedd9f6249f24c0e5d2e7337734a3d696df99098862eae2849dc455255a1d21db6eab50b2d60bac862358b1a922c5e0ed6fcf09ab42ba82e34d45fdf141706a80926822236553725cfc18edab0066761dd6c6c42afc04cdc7751516b84417ccb95e3a8cb1245cf25f2f62cb691beca7830f1a4c42b94399101ca2ba5446f2f6c397f51be765299c635c01b50a52ee449afd9b77f1f6d8475df7d908ec889b432905065a15e419323c9fc82334acb737d48712db486e84681b96a0fb6f78fa6066eaf5631c10654e8558811f0bbe0ce5fae8ad8eb8350911b684d11647a64f5dc077874e3ec1f9e843128208394214ea82665ca7e046126ad3641c69a9fb6610937f33a9d818d07f78447cafd86cac5c9917c1e9a308062fe98411d9e58debb4dd3e9505d435511963ef6086dd607c2f100bbf7892353cb9ed660ddfa20b06e987c4bdb5c96869b5af01057f0daeb8804786a84b582457fad5f046d9166060aad9e18540c5997e7cd7bbb904b9bd62d25b4e4b64b0349c288909657c037d5efedf4010f0908e90af605ae2effdb1ce018df709f7b18c40c37e728b8933cac9495ec07f15c994eb03a449cb904db51d14db5de6020194fc0221282a1df86098b0640160306b08521b5391ba8a86929aa138eb9ebd9171f5f46a32d57947e230b25cebbfdeae5596b97eb244b8811b942d58639e8e039f08b5819ea3a2e5164b1ada30c8fa8db81d85d1a5ec175d1754400d0a0d213a24d11529123ae156593aeb78a317d3206db9365e4060308325e43bbcdad3ea6013f30bea84118efaa7276debcf869a335e8bc5a4cd96d0c55a78241982109443d554f4380a3b959d9ef923634bce67b4b5e5144ff3e6e1524b611915d001c080511a11669295ce053d33644ccfd89c578f9027e686a67a7b345a912da6c1f3c1ffd9e340a069e23892dab84a4ac618e428c8e2c48ffdde9db565fd8c446e44826a94359639cd0f43b9b7922901c945e818ff81c6112f3f8ee7dae710c75b6c130039f0bf213227abda5d307103ec6c80d637cbc87bc6f539a0f6ea6feb33f34195fe1de92e349ab83b9f254cca1fa16072d832b4b37ca44ab5a6734a7f04067809148b0f17aa7a688645f303ffc24538068936993c2fc636fd6b958b222258b3658a830a6810fcc31ca99a8983730b5b64fc14d4c2b1056353147a2c76878620be0930b0181501c4ec1abde68ce639d8900619f7b0e469b1e4707cd4908e9d40a17e6b8fcd255fe6d241f832858a017a9d62e59b2c2e727a4ec00ff98ad80c4bfd538b91feb1976835dcf974330e77f7d2cc70bcdab9d21720071bfaffc1571201154901a411d5694649e233bf2d6fe7b62a79c901f3e7417a2337ca88048e2837c611181ec623f5810ee0c456f974285f7d7d2a592ace443c54d6cdc223e2026 diff --git a/zebra-test/src/vectors/orchard_shielded_data.rs b/zebra-test/src/vectors/orchard_shielded_data.rs new file mode 100644 index 00000000000..b117cdd007a --- /dev/null +++ b/zebra-test/src/vectors/orchard_shielded_data.rs @@ -0,0 +1,34 @@ +//! Orchard shielded data (with Actions) test vectors +//! +//! Generated by `zebra_chain::primitives::halo2::tests::generate_test_vectors()` +//! +//! These are artificial/incomplete `zebra_chain::orchard::ShieldedData` +//! instances, care should be used when using them to test functionality beyond +//! verifying a standalone Orchard Acton Halo2 proof. + +#![allow(missing_docs)] + +use hex::FromHex; +use lazy_static::lazy_static; + +lazy_static! { + pub static ref ORCHARD_SHIELDED_DATA: Vec<&'static [u8]> = [ + ORCHARD_SHIELDED_DATA_1_BYTES.as_ref(), + ORCHARD_SHIELDED_DATA_3_BYTES.as_ref(), + ORCHARD_SHIELDED_DATA_3_BYTES.as_ref(), + ORCHARD_SHIELDED_DATA_4_BYTES.as_ref(), + ] + .to_vec(); + pub static ref ORCHARD_SHIELDED_DATA_1_BYTES: Vec = + >::from_hex(include_str!("orchard-shielded-data-1.txt").trim()) + .expect("Orchard shielded data bytes are in valid hex representation"); + pub static ref ORCHARD_SHIELDED_DATA_2_BYTES: Vec = + >::from_hex(include_str!("orchard-shielded-data-2.txt").trim()) + .expect("Orchard shielded data bytes are in valid hex representation"); + pub static ref ORCHARD_SHIELDED_DATA_3_BYTES: Vec = + >::from_hex(include_str!("orchard-shielded-data-3.txt").trim()) + .expect("Orchard shielded data bytes are in valid hex representation"); + pub static ref ORCHARD_SHIELDED_DATA_4_BYTES: Vec = + >::from_hex(include_str!("orchard-shielded-data-4.txt").trim()) + .expect("Orchard shielded data bytes are in valid hex representation"); +}